What “Static” and “Dynamic” Actually Mean
Every response a web server sends to a browser is a static file. Even on a heavily dynamic site, the HTML, CSS, JavaScript, and images your browser receives could be saved to a USB drive and shared like any other file. The distinction between “static” and “dynamic” comes down to what the server does before it responds.
On a static site, the requested file already exists on the server and is sent back unchanged. On a dynamic site, the response is generated by software at request time; that software may query a database, assemble templates, and inject data before sending the result. Static sites just serve files; dynamic sites run code to produce those files.
The Jamstack Middle Ground
Jamstack is not a specific technology stack. It’s an approach that inherits the core benefits of static sites—security, performance, low operational overhead—while permitting dynamic behavior where it’s actually needed. The key architectural idea is a clean separation: the front end is decoupled from the back end, content is prerendered whenever possible, and dynamic services are layered on top as APIs.
This philosophy has roots in Aaron Swartz’s “bake, don’t fry” idea from 2002: keep a strict separation between input (which needs dynamic code) and output (which can usually be baked ahead of time). The same motivations drove early tooling like MovableType, Jekyll, and Hugo—reducing complexity, improving performance, and giving developers simpler workflows.
The practical benefits of a Jamstack architecture cluster around six areas:
- Security: fewer moving parts means less attack surface.
- Scale: static output can be served entirely from a CDN, making traffic spikes cheap and easy.
- Performance: serving files from a CDN edge beats generating a page at a central server on every request.
- Maintainability: a static site needs minimal upkeep compared to a dynamic application stack.
- Portability: because everything is files, you can move the site to any capable web server.
- Developer experience: file-based sites fit naturally into Git-based workflows—something many legacy CMSs make cumbersome.
Edge Cases: Drawing the Lines
Reality is messier than definitions. To understand where static ends and Jamstack or dynamic begins, it helps to work through gray-area cases. These edge cases fall into four buckets: strictly static, basically static, Jamstack, and dynamic.
Still Static
Several common additions don’t change a site’s static nature. Client-side JavaScript interactions—say, an image slideshow—manipulate already-delivered HTML in the browser; all the files are static. A cookie-triggered banner is likewise static; cookies are just HTTP headers changed by browser-side code, not by the server.
Infrastructure can also be added without crossing the line. A reverse proxy in front of a static webserver is fine; if the file on disk is byte-for-byte what the browser receives, the site remains static. A CDN is just a globally distributed reverse proxy, and CDN-added headers aren’t part of the stored file. Even a WordPress site becomes effectively static if you use something like WP2Static to pre-render and serve plain HTML output; the browser requests files that already exist.
Basically Static
Some setups violate the strict definition but no one would call them dynamic. Loading third-party assets such as an image CDN or external JavaScript means part of the page is generated outside your control. Most people would describe that site as static nonetheless. Embedded iframes—a YouTube video, a Google Map—are similar; the embedding page is static even though the embedded content comes from a dynamic source.
Forms sit in the same gray zone. A static page can certainly contain a form, and plenty of form services sit behind the submission endpoint. Whether that breaks “static” depends on how much of your core workflow lives on the remote service; in practice, most developers would still call it a static site.
The Jamstack Threshold
Jamstack starts where the “static” adjective no longer holds up honestly. Once your site relies on Ajax requests to pull dynamic data from an external API, you’re using a front end decoupled from a back end. If a page makes an Ajax call for data—even from a serverless function, a containerized API, or a classic PHP endpoint—you’ve left pure static territory. The front end is prerendered where possible, and dynamic content is fetched at runtime. This exact pattern also describes embedded eCommerce widgets and single-page applications that render a dynamic presentation layer entirely on the client.
The Jamstack minus occurs only when you attempt to mix a static experience with backend administration.
Still a Dynamic Deployment
Several strategies attempt to address a real limitation of pre-rendering—long build times—but in doing so, they leave the static and Jamstack camps. Distributed Persistent Rendering builds pages on demand the first time they’re requested, caching the result for future visitors. It feels more static than a CDN in front of a dynamic site, but generating a page with software at request time is a dynamic operation. Incremental Static Regeneration is comparable; it generates or revalidates individual pages periodically without affecting the rest of the site. Both are dynamic because there’s no strict separation between the generation step and the delivery layer, and neither is portable in the way file-based static output is.
Flat-file CMSs also render pages dynamically; removing a database from the stack doesn’t change that the response is generated by code on every request. Even a site served behind a CDN with an absurdly long cache header isn’t static if the origin generates the first response on demand—CDNs aren’t a persistent store, and they can always fall back to the raw dynamic origin.
Edge computing deserves a closer look. Running code at the CDN edge, such as adding a response header, doesn’t change your site’s fundamental requirements; the file you stored is the file the user receives. But the moment you manipulate HTML at the edge, adjusting content or injecting data per request, you’re operating a dynamic service. You’ve also introduced a piece of core infrastructure that lives only on your hosting platform, and you’ve lost the separation of concerns that defines Jamstack.
Choosing Where You Stand
None of these tradeoffs are inherently wrong. If the front end needs to know a visitor’s country, you have two legitimate options: fetch the country with an Ajax call after the page loads—a classic Jamstack approach with graceful degradation—or inject the country code into the HTML with an edge function so it’s immediately available. The best choice depends on whether that information is a nice-to-have or a hard requirement.
Drawing these lines isn’t about being puritanical. The value is in having a precise vocabulary for the operational tradeoffs: moving toward fully prerendered static output improves speed, security, scalability, and reliability. Pushing dynamic behavior up the stack buys flexibility at the cost of simplicity and portability. Whether the page arrives pre-baked from a CDN or hot out of a request-time oven depends entirely on the problem you’re solving.



