Static vs Dynamic Website: Choose the Runtime by What Must Change

Playcode Team
14 min read
#static vs dynamic website #web architecture #website planning

QUICK ANSWER

What is the difference between a static and dynamic website?

A static website serves prebuilt files, even if browser JavaScript adds interaction. A dynamic website generates or personalizes content from request-time data and often writes durable state. Choose static for mostly shared public content, dynamic for identity, permissions, fresh records, or server actions, and hybrid when public pages can be prebuilt but account or workflow routes need a runtime.

This article uses dynamic to mean request-time server behavior or durable application state. Animation, browser JavaScript, or a static page calling an external API does not by itself make the whole site dynamically rendered. The useful distinction is when HTML is prepared, where durable state lives, and which system owns each request and record.

This guide compares three practical shapes: static or prerendered pages, dynamic server-backed pages, and a hybrid that assigns each route to the smallest sufficient boundary. It uses the same ten criteria for every option so a search, security, speed, or cost slogan cannot decide the architecture by itself.

Static build-time delivery and dynamic request-time delivery joined in a hybrid route map
Illustrative architecture map, not a product screenshot. Static, dynamic, and hybrid are route-level delivery choices, not performance or security grades. The actual result depends on the brief.

Complete the Runtime Boundary Matrix

Use four sourced passes to choose per route, then write the exact requirement that would reopen the decision. This is a decision method, not a universal build recipe.

  1. Inventory what can vary

    List each route, its audience, whether output is shared or viewer-specific, the authoritative content source, update frequency, identity and write behavior, and maximum acceptable staleness. Keep browser interaction separate from the server rendering decision.

    Sources: [mdn-server-side], [astro-on-demand]

  2. Name the cache contract

    For every public response, state its cache key, freshness rule, validator or revalidation path, invalidation event, and whether stale delivery is allowed during failure. Isolate private responses so viewer-specific state cannot cross a shared cache key.

    Sources: [rfc9111-cache], [nextjs-caching]

  3. Name ownership and recovery

    Identify the authoritative content and data stores, export and retention owners, backups, artifact or code rollback, data restore, and recovery verification. A prior release can recover files or code without recovering mutable records.

    Sources: [cloudflare-rollbacks], [postgres-backup]

  4. Choose per route and record the migration trigger

    Select prebuilt static delivery, request-time dynamic delivery, or a hybrid, then state the new freshness, identity, write, recovery, accessibility, or crawl requirement that would change the choice. Preserve URL and canonical ownership through any later move.

    Sources: [astro-on-demand], [google-js-seo], [wcag22]

What this comparison means by static, dynamic, and hybrid

The labels describe response production and state boundaries, not visual design, JavaScript animation, or a vendor category.

Included

  • Static rendering and prerendering that produce HTML before a visitor requests the route
  • Dynamic server-backed rendering that can use request, identity, application, or database state
  • Hybrid systems that select build-time or request-time behavior per route or data boundary
  • Public-search, cache, access, deployment, recovery, migration, and operating-cost decisions

Not included

  • A claim that all static sites avoid JavaScript or all dynamic sites use server-side HTML rendering
  • Hosting-provider rankings, price tables, plan comparisons, or vendor recommendations
  • A framework or CMS ranking
  • A universal performance benchmark or category-wide speed, safety, cost, uptime, conversion, or search promise
  • Native mobile delivery, offline-first application design, or background device behavior
  • Guaranteed speed, safety, uptime, cost, conversion, or search rankings for any category

Ten criteria that force a real decision

Use the complete set for every option. A single fast demo, simple deploy, or authenticated screen cannot stand in for the production contract.

When HTML is produced

Separates build-time output from request-time execution without confusing the choice with browser animation.

How content becomes current

Shows whether a rebuild, cache revalidation, or request-time data read owns freshness.

Identity and durable writes

Reveals when accounts, permissions, sessions, and authoritative records require a server boundary.

Cache behavior and invalidation

Prevents cached from being treated as automatically fresh or safe for personalized data.

Source of truth and custody

Forces the team to name who owns content, records, export, retention, backup, and restore.

Deployment and rollback unit

Distinguishes rolling back generated files from recovering mutable data and schema state.

What can fail at build and request time

Makes stale content, origin outage, database failure, and provider failure visible before launch.

Inputs, sessions, authorization, and scripts

Avoids the false claim that static means secure or that dynamic risk is solved by a framework.

Accessible and indexable output

Keeps semantics, status codes, rendered content, canonical URLs, and WCAG requirements independent of architecture labels.

What changes the decision

Gives the reader a reversible starting point rather than a permanent binary label.

Runtime Boundary Matrix

Compare all ten rows before selecting a model. There is no score or universal winner; each route must preserve its own freshness, data, access, release, recovery, accessibility, and crawl contract.

Prebuilt static delivery

Best for: Shared public content, portfolios, documentation, campaigns, and service sites whose owned content can update through a controlled build and publish cycle.

The build emits files that the server returns without running page-generation code for each request. Browser JavaScript can still add interaction, and every external API remains a separate dynamic dependency and data owner.

Prebuilt static delivery: Ten criteria that force a real decision
CriterionFinding
When HTML is producedThe build emits files that the server returns for a URL without running page-generation code for each request. Browser JavaScript may still add interaction. Sources: [mdn-server-side], [astro-on-demand]
How content becomes currentOwned content normally changes through its source plus a rebuild and deploy. Client-fetched data may change faster, but that external API then owns the dynamic dependency. Sources: [astro-on-demand], [cloudflare-builds]
Identity and durable writesA static frontend can submit a form or call an API, but identity, validation, authorization, and durable writes live in that service rather than in the generated files. Sources: [mdn-server-side], [owasp-input], [owasp-session]
Cache behavior and invalidationPublic files are strong cache candidates, but freshness, validators, variation, and invalidation still need explicit policy. A cached response is not automatically current. Sources: [rfc9111-cache]
Source of truth and custodyThe repository, CMS, or build input owns published content. Generated output is a release artifact, not an authoritative store for user records. Name every external form, CMS, and API owner separately. Sources: [cloudflare-builds], [mdn-server-side]
Deployment and rollback unitDeploy the generated output and roll back to a previous successful artifact when the host supports it. This restores files, not external databases or provider state. Sources: [cloudflare-builds], [cloudflare-rollbacks]
What can fail at build and request timeBuilds can fail before release; assets can be missing or stale after release; caches may continue serving a prior response under allowed conditions. An external API can still fail at request time. Sources: [cloudflare-builds], [rfc9111-cache]
Inputs, sessions, authorization, and scriptsRemoving an owned request-time server can reduce one attack surface, but third-party JavaScript, forms, client code, dependencies, headers, and external APIs still require review. Static does not mean secure by default. Sources: [owasp-third-party-js], [owasp-input]
Accessible and indexable outputPrerendered HTML can expose content early, but the page still needs semantic HTML, crawlable links, correct status and canonical behavior, and WCAG-conformant interaction. It does not guarantee rankings or accessibility. Sources: [google-js-seo], [wcag22]
What changes the decisionPromote only routes that acquire a hard request-time need: viewer-specific responses, protected state, server actions, or freshness that cannot meet its requirement through rebuild or controlled revalidation. Sources: [astro-on-demand], [nextjs-caching]

Tradeoffs

  • Broadly cacheable artifacts can simplify public delivery, but rebuild, deployment, validation, and invalidation still own freshness.
  • A smaller owned runtime surface does not remove form, third-party script, API, domain, privacy, accessibility, or security responsibilities.

Request-time dynamic delivery

Best for: Signed-in or personalized experiences, current database-backed records, server actions, protected workflows, and routes whose value depends on request-time state.

Server code handles the request and can combine templates with request, identity, or database state before returning the response. Public dynamic output may still be cached when its key and freshness contract are safe.

Request-time dynamic delivery: Ten criteria that force a real decision
CriterionFinding
When HTML is producedServer code handles the request and can combine templates with database or request data before returning a response. Sources: [mdn-server-side], [astro-on-demand]
How content becomes currentResponses can use current request, user, or database data without rebuilding the whole site, subject to application and cache policy. Sources: [mdn-server-side], [astro-on-demand]
Identity and durable writesSessions, authenticated views, permissions, validation, and durable record changes require explicit server-side controls and lifecycle rules. Sources: [owasp-input], [owasp-session], [mdn-server-side]
Cache behavior and invalidationPublic dynamic responses may be cached or revalidated. Private and viewer-specific variants must not leak across cache keys; state-changing requests need correct invalidation and reconciliation. Sources: [rfc9111-cache], [nextjs-caching]
Source of truth and custodyThe database, object store, identity system, and provider records become named sources of truth. Export, retention, backup, and restore need owners independent of code. Sources: [postgres-backup], [mdn-server-side]
Deployment and rollback unitDeploy application code, runtime configuration, and compatible schema changes. Rolling code back does not automatically reverse data writes, so recovery must cover the data layer explicitly. Sources: [postgres-backup], [cloudflare-rollbacks]
What can fail at build and request timeRuntime, database, cache, identity, and external-provider failures can affect live requests. Define timeouts, retry safety, degraded behavior, monitoring, and restore exercises. Sources: [mdn-server-side], [rfc9111-cache], [postgres-backup]
Inputs, sessions, authorization, and scriptsValidate untrusted input on the server, enforce authorization independently of the interface, and protect authenticated sessions across their full lifecycle. Sources: [owasp-input], [owasp-session]
Accessible and indexable outputServer-rendered HTML can be crawlable and accessible, but client-only content can add rendering delay and weak error states. Use meaningful statuses, stable canonicals, semantic output, and WCAG checks. Sources: [google-js-seo], [google-dynamic-rendering], [wcag22]
What changes the decisionPrerender routes whose output is public and changes less often than requests arrive. Keep request-time execution only where it carries real freshness, identity, or state value. Sources: [astro-on-demand], [nextjs-caching]

Tradeoffs

  • Current data and server authority support protected workflows while adding runtime, database, schema, secret, monitoring, access, and recovery obligations.
  • Request-time HTML can be accessible and crawlable, yet uncached generation, slow data, or client-only states can still hurt the result.

Hybrid by route

Best for: Products that need indexable public acquisition and trust pages plus authenticated or operational workflows.

The architecture assigns build-time or request-time behavior per route. It keeps stable public delivery and server-backed workflows inside explicit, separately tested cache, access, failure, and recovery boundaries.

Hybrid by route: Ten criteria that force a real decision
CriterionFinding
When HTML is producedPrerender stable public routes and render only selected routes on demand. Modern frameworks support route-level choices rather than one label for the entire project. Sources: [astro-on-demand], [nextjs-caching]
How content becomes currentUse rebuilds for slow-changing public content, controlled revalidation for bounded freshness, and request-time reads for user-specific or immediately current records. Sources: [astro-on-demand], [nextjs-caching], [rfc9111-cache]
Identity and durable writesKeep public acquisition content static while authenticated account, portal, or operator routes use server-enforced identity, permissions, and durable records. Sources: [mdn-server-side], [owasp-session]
Cache behavior and invalidationCache public output broadly, isolate or disable caching for private responses, and document invalidation where a write changes a public representation. Sources: [rfc9111-cache], [nextjs-caching]
Source of truth and custodyName separate sources of truth for public content and application records, plus the contract that publishes shared facts between them. Sources: [mdn-server-side], [postgres-backup]
Deployment and rollback unitKeep a recoverable artifact for public pages and a separately tested runtime and data recovery plan. Coordinate shared schema or content contracts during rollback. Sources: [cloudflare-rollbacks], [postgres-backup]
What can fail at build and request timeThe public site can remain available during some runtime failures, but sign-in and stateful transitions need explicit unavailable, retry, and support states. Sources: [rfc9111-cache], [postgres-backup]
Inputs, sessions, authorization, and scriptsSeparate public and authenticated cookies, scripts, cache rules, and authorization boundaries. A shared navigation shell must not blur access control. Sources: [owasp-session], [owasp-third-party-js]
Accessible and indexable outputPrerender indexable public routes, keep private or low-value states out of search where appropriate, and apply the same WCAG requirements across both surfaces. Do not use crawler-only dynamic rendering as the architecture. Sources: [google-js-seo], [google-dynamic-rendering], [wcag22]
What changes the decisionReview decisions per route when freshness, identity, write, recovery, or crawl requirements change. Do not migrate the entire site because one route needs a server. Sources: [astro-on-demand], [nextjs-caching]

Tradeoffs

  • Each route can use the smallest sufficient runtime, while the team must test and operate both delivery modes and the transition between them.
  • Public pages may survive some runtime outages, but shared content, identity, navigation, cache policy, releases, and support can drift.

Choose the boundary route by route

Prefer the smallest boundary that preserves the required freshness, authority, access, and recovery contract. Reopen the decision when one of those requirements changes.

  1. The route is public, shared by every visitor, and can change through a deliberate content release

    Choose: Use static rendering or prerendering for that route.

    Tradeoff: Urgent or very large content updates may require incremental builds, targeted regeneration, or a later route split.

  2. The response depends on current identity, permissions, live records, or a server-enforced business rule

    Choose: Use a dynamic server-backed boundary for that route and operation.

    Tradeoff: You accept runtime, data, session, monitoring, migration, and recovery responsibilities that a prebuilt page does not need.

  3. The product needs public discovery pages and a protected workflow with durable user-specific state

    Choose: Use a hybrid with an explicit public-to-private transition.

    Tradeoff: Navigation, identity, domains, analytics, content ownership, releases, and support must stay coherent across both surfaces.

  4. A static page submits to an external form, API, search service, or commerce provider

    Choose: Keep the frontend classification separate from the external service contract.

    Tradeoff: The service still owns validation, data custody, privacy, availability, retries, and recovery even when the page files are prebuilt.

  5. Public freshness can be bounded by a stated staleness window

    Choose: Use caching and revalidation deliberately before adding request-time rendering everywhere.

    Tradeoff: The team must own the cache key, validator, invalidation event, stale behavior, and monitoring rather than assume freshness is automatic.

  6. Rollback must restore mutable application records or schema state

    Choose: Require a separately tested data backup, restore, repair, and reconciliation path.

    Tradeoff: Artifact or code rollback alone cannot reverse later valid writes and may create a new consistency problem.

  7. The decision is uncertain and no hard identity, permission, write, or request-time freshness need exists

    Choose: Start with prebuilt public routes and write the exact migration trigger before launch.

    Tradeoff: A later route move needs URL, data, cache, access, accessibility, canonical, and recovery parity, so record those contracts now.

MAP THE BOUNDARY

Describe the content, state, and access before the stack

Give Playcode the public routes, durable records, user roles, freshness rules, and recovery needs. Build one production-shaped path that can prove the architecture choice.

Start Building

The first slice should test the riskiest boundary, not assume every route needs a server.

Limits of this comparison

The guide supplies a decision model, not a benchmark result or procurement answer for every framework and provider.

  • Framework defaults, hosting behavior, cache implementations, and platform limits change; verify the exact stack before release.
  • The guide does not measure your payload, traffic, build duration, request latency, cache-hit rate, database workload, or incident cost.
  • A static shell can depend on dynamic services, and a dynamic application can serve static assets; real dependency graphs matter more than labels.
  • SEO depends on relevance, crawlability, status and canonical correctness, useful content, links, and competition. No rendering category guarantees rankings.
  • Security depends on implementation and operation. Static is not automatically safe, and server-backed is not automatically unsafe.
  • Regional hosting, data-residency, accessibility, legal, privacy, and compliance requirements need separate review.

Primary sources and review record

These sources define the architecture and controls used in the comparison. Access dates record this review, not a promise that every page was revised on that date.

  1. [mdn-server-side] MDN Web Docs:Introduction to the server side

    Checked August 1, 2026. Supports: The static-response and dynamic server-side request model, including database-backed response generation and server responsibilities.

  2. [astro-on-demand] Astro Documentation:On-demand rendering

    Checked August 1, 2026. Supports: Build-time prerendering, request-time server rendering, per-route hybrid choices, runtime adapters, cookies, responses, and data lookups.

  3. [nextjs-caching] Next.js Documentation:Caching with Cache Components

    Checked August 1, 2026. Supports: The current Cache Components model, including cache keys, static shells, request-time APIs, streaming uncached data, and explicit revalidation boundaries.

  4. [rfc9111-cache] RFC Editor:RFC 9111: HTTP Caching

    Checked August 1, 2026. Supports: Freshness, age, validation, validators, stale-response rules, variation, authenticated responses, and invalidation after unsafe methods.

  5. [google-js-seo] Google Search Central:Understand JavaScript SEO Basics

    Checked August 1, 2026. Supports: Google crawling, rendering, indexing, link discovery, status-code, canonical, and rendered-content guidance for JavaScript sites.

  6. [google-dynamic-rendering] Google Search Central:Dynamic rendering as a workaround

    Checked August 1, 2026. Supports: Crawler-specific dynamic rendering is a workaround rather than a recommended architecture.

  7. [wcag22] W3C:Web Content Accessibility Guidelines 2.2

    Checked August 1, 2026. Supports: Technology-independent accessibility requirements for perceivable, operable, understandable, and robust web content.

  8. [owasp-third-party-js] OWASP Cheat Sheet Series:Third Party JavaScript Management Cheat Sheet

    Checked August 1, 2026. Supports: Third-party script integrity, change, availability, privilege, and data-disclosure risks on static or dynamic pages.

  9. [owasp-input] OWASP Cheat Sheet Series:Input Validation Cheat Sheet

    Checked August 1, 2026. Supports: Early syntactic and semantic validation of untrusted input before processing and persistence.

  10. [owasp-session] OWASP Cheat Sheet Series:Session Management Cheat Sheet

    Checked August 1, 2026. Supports: Authenticated state, session identifiers, access-control binding, secure cookies, and session lifecycle risk.

  11. [postgres-backup] PostgreSQL Documentation:Backup and Restore

    Checked August 1, 2026. Supports: The need for regular database backups and an understood SQL dump, file-system backup, or continuous-archiving restore method.

  12. [cloudflare-builds] Cloudflare Documentation:Cloudflare Pages build configuration

    Checked August 1, 2026. Supports: Build commands, output directories, root-directory configuration, and the difference between command success and uploaded output.

  13. [cloudflare-rollbacks] Cloudflare Documentation:Cloudflare Pages rollbacks

    Checked August 1, 2026. Supports: Artifact-level rollback to a prior successful production deployment and the boundary around preview deployments.

Static and dynamic website questions

Can a static website use JavaScript?

Yes. Browser JavaScript can add interaction without making the server generate HTML per request. Classify the prebuilt frontend separately from every API it calls, because those services add request-time dependencies, untrusted-input boundaries, private data owners, cache rules, and failure modes.

Does using a CMS make a website dynamic?

Not necessarily. A CMS can supply content to a static build, answer requests at runtime, or support both modes. Follow one URL from the content source through build or request-time rendering, cache and invalidation, response, and rollback. That path determines the model more reliably than the CMS label.

Can a static website have forms?

Yes, through an external service or a server endpoint. The page files remain prebuilt, but validation, authorization where needed, data custody, delivery, privacy, retry behavior, and recovery move to that service. Show success only after the intended durable record or delivery boundary has returned a trustworthy result.

Are static websites always better for SEO?

No. Prerendered HTML is straightforward for crawlers to receive, but dynamic server-rendered pages can also be indexed. Useful content, ordinary links, meaningful status codes, stable canonicals, rendered output, accessibility, and competition still matter. No rendering architecture guarantees indexing, traffic, or rankings.

Are dynamic websites always slower or more expensive?

No. Results depend on runtime, data access, cache-hit rate, payload, traffic, implementation, incidents, and operating requirements. Static delivery still pays for builds, storage, delivery, external services, content operations, and owner time. Compare the real production meters rather than publishing one universal speed or cost claim.

Is a single-page application static or dynamic?

It can be deployed as static files while fetching dynamic data from APIs. Classify the HTML and asset delivery separately from authentication, API calls, durable records, and server actions. Also test meaningful loading and error states, public status and canonical behavior, and what remains usable or visible before client JavaScript completes.

When should a static site become dynamic?

Promote a route when a hard requirement appears for identity, server-enforced permissions, viewer-specific data, durable writes, server actions, or freshness the current build and revalidation contract cannot satisfy. Move the narrowest route cohort and preserve URLs, data, cache, access, recovery, and search behavior.

Can one website be both static and dynamic?

Yes. A route-level hybrid can prerender public acquisition, help, policy, or documentation pages while account and workflow routes use a runtime. Define separate cache and access rules, shared source-of-truth fields, coordinated releases, unavailable states, and artifact versus data recovery before calling the split complete.

PROVE ONE ROUTE

Build the smallest architecture that preserves the real workflow

Start with one public page, one stateful route, or the transition between them. Test the response, access, cache, failure, and recovery contract before scaling.

Start Building

No credit card required. AI credits are included to start; production requirements and plan limits still apply.

Have thoughts on this post?

We'd love to hear from you! Chat with us or send us an email.