Migrate Your Drupal Site to a Static Site
Drupal was built for complex content management. Its entity/field architecture, granular permissions, editorial workflows, and multilingual capabilities make it a serious platform for serious publishing operations. Universities, government agencies, and enterprises choose Drupal because they need its power.
But power comes with infrastructure. Running Drupal means maintaining a PHP application server, a relational database, a caching layer (often Varnish or Redis), a web server configuration, and a constant stream of security patches for both core and contributed modules. For a site that exercises Drupal’s advanced features, this infrastructure earns its keep.
The question for many Drupal site owners, though, is whether their site actually uses what Drupal provides. A marketing site with 30 pages, a blog, and a contact form does not need entity references, content moderation workflows, or granular role-based permissions. It needs HTML served to visitors. And for that job, a static site — pre-built HTML served from a CDN — is architecturally simpler, dramatically faster, and costs nearly nothing to operate.
This guide covers the honest case for going static, the practical approaches for getting there, and the situations where staying on Drupal is the right call.
What “going static” actually means
A static site generator (Astro, Hugo, 11ty, Next.js in static mode) takes your content — typically markdown files with YAML frontmatter — and produces a folder of HTML, CSS, JavaScript, and image files at build time. These files are uploaded to a CDN (content delivery network) and served directly to visitors. There is no server-side processing at request time.
Drupal’s architecture:
Visitor request → CDN/Load Balancer → Web Server (Apache/Nginx)
→ PHP Runtime → Drupal Bootstrap → Database Query
→ Cache Layer Check → Render HTML → Send Response
Even with Varnish or page caching in front, the infrastructure exists. The database is running. PHP is running. Security patches are accumulating. If the cache misses, the full stack executes.
Static site architecture:
Visitor request → CDN Edge Node → Serve pre-built HTML file
That is it. No PHP, no database, no cache invalidation, no server-side processing. The HTML was built minutes or hours ago and is sitting on CDN edge nodes around the world.
A fair performance comparison
The internet is full of cherry-picked performance comparisons. Here is a fair one.
A well-optimized Drupal site with Varnish page cache, Redis for backend caching, a CDN for static assets, and proper cache tag management can serve pages in 100-300ms with good Core Web Vitals scores. Drupal’s BigPipe and cache API are genuinely sophisticated. Acquia, Pantheon, and Platform.sh all offer Drupal hosting with excellent performance tuning.
A static site serves pre-built HTML from a CDN edge node in under 50ms with perfect or near-perfect Core Web Vitals scores. There is no optimization required because there is nothing to optimize — it is just files.
The performance gap between “well-optimized Drupal” and “static” is real but not as dramatic as some claim. The gap between “typical Drupal” and “static” is much larger:
| Metric | Typical Drupal | Optimized Drupal | Static Site |
|---|---|---|---|
| TTFB | 500ms-2s | 100-300ms | <50ms |
| Core Web Vitals pass rate | ~59% (httparchive.org) | 80-90% | 95-100% |
| Page weight | 1-5MB (with contrib module CSS/JS) | 500KB-1MB (optimized) | 50-300KB |
| Lighthouse performance | 40-70 | 80-95 | 95-100 |
The honest takeaway: if you are investing heavily in Drupal performance optimization (dedicated DevOps, Varnish tuning, Redis configuration, CDN setup), you can get good results. But a static site achieves better results with zero optimization effort.
Cache invalidation is the key difference. Drupal’s cache system is powerful but complex — cache tags, cache contexts, cache max-age, and the interplay between page cache, dynamic page cache, and internal page cache. Getting it right requires Drupal-specific expertise. A static site has no cache invalidation problem because the “cache” is the site itself, rebuilt from scratch on every content change.
The cost of running Drupal
Drupal’s costs are well-documented in the community:
Managed hosting: $100-$500/month for platforms like Acquia, Pantheon, or Platform.sh. Cheaper options exist ($20-$50/month for basic VPS setups), but they require more hands-on server management.
Maintenance and updates: Drupal core releases security updates regularly. Contributed modules release updates constantly. Each update needs testing to ensure compatibility. Organizations typically spend $3,600-$24,000/year on maintenance, either through retainer agreements with Drupal agencies or internal developer time.
Developer rates: Drupal specialists command $50-$200/hour. The Drupal talent pool, while dedicated and skilled, is smaller than the general JavaScript developer market. Finding Drupal developers, especially for legacy D7 sites, is increasingly difficult.
Five-year total cost of ownership for a mid-size Drupal site: $36,000-$100,000+ in hosting and maintenance alone, before any new feature development.
Static site costs:
| Item | Cost |
|---|---|
| Hosting (Cloudflare Pages, Vercel, Netlify free tiers) | $0/month |
| Domain name | $10-15/year |
| Annual maintenance | Near-zero (no server, no database, no patches) |
| Developer rates (for changes) | Any JavaScript developer or AI coding agent |
| Five-year total | Under $100 (excluding development time for changes) |
The cost comparison is stark, but it is also slightly misleading. A Drupal site’s cost includes features (editing UI, permissions, workflows) that a static site does not provide out of the box. If you need those features and add a headless CMS to your static site, costs go up. The savings are real for sites that do not need Drupal’s content management features.
Drupal 7 end of life: the forcing function
Drupal 7 reached end of life in January 2025. For the many organizations still running D7 sites, this creates urgency. Unsupported software means no security patches, no bug fixes, and increasing compliance risk.
The options for D7 sites:
1. Upgrade to Drupal 10/11. The official path. This is not a simple version update — it is essentially a rebuild. D7’s hook-based architecture, PHPTemplate theme layer, and field storage schema are fundamentally different from D10’s plugin-based architecture, Twig templates, and entity API. Custom modules must be rewritten. Themes must be rebuilt. Database schemas must be migrated.
Timeline: 3-6 months. Cost: $50,000-$200,000 depending on complexity.
2. Extended D7 support. Third-party vendors like my Drop Wizard and Tag1 offer paid D7 security patches. This buys time but does not solve the underlying problem — you are still on an aging platform with a shrinking module ecosystem and developer pool.
Cost: $1,000-$5,000/year for patches, plus ongoing hosting and maintenance.
3. Migrate to a static site. Extract content, rebuild as static HTML. For D7 content sites, this is often the most cost-effective path.
Timeline: Days to weeks. Cost: $0-$10,000 depending on approach.
4. Migrate to WordPress. Some organizations choose WordPress as an intermediate step — it offers a CMS editing experience with lower infrastructure requirements than Drupal. This is a valid approach if you want to stay on a traditional CMS.
For D7 sites that are primarily serving content, option 3 is worth serious consideration. But be honest: if your D7 site genuinely uses Drupal’s advanced features (complex permissions, entity references driving application logic, multilingual with translation workflows), the D10 upgrade may be the right investment.
How to migrate: every approach available
1. AI coding agents (Claude Code, Cursor, Windsurf, Cline)
The most powerful approach for developers. Drupal’s content extraction APIs are excellent, and AI agents can consume them directly.
For Drupal 8+ sites:
Drupal 8+ ships with JSON:API as a core module. It exposes every entity type as a RESTful endpoint:
GET /jsonapi/node/article?page[limit]=50&filter[status]=1
GET /jsonapi/node/page?include=field_image
GET /jsonapi/taxonomy_term/tags
GET /jsonapi/media/image
An AI coding agent (Claude Code, Cursor, Windsurf, Cline) can consume these endpoints, extract all content and media, and scaffold a static site project:
- Confirm JSON:API is enabled: visit
https://your-site.com/jsonapi - Open your preferred AI agent
- Prompt: “Fetch all published content from my Drupal site at example.com using JSON:API. For each content type, create markdown files with frontmatter. Download all images. Build a static site with Astro (or Hugo/11ty). Preserve URL aliases for SEO.”
- The agent iterates through endpoints, creates files, downloads media
- Review, adjust, rebuild until the site is ready
- Deploy to a static host
For Drupal 7 sites:
D7 does not have JSON:API. Export content via:
- Direct SQL queries against
field_data_*tables (most reliable) - Views Data Export module (create Views that export as CSV/JSON)
- Services module (REST API for D7, requires installation)
- Drush (
drush sql-queryfor targeted exports,drush sql-dumpfor full database)
Feed the exported data to an AI agent for conversion to markdown and project scaffolding.
Crawling approach (any version):
If API and database access are unavailable, an AI agent can crawl the published site, extract content from HTML, download images, and rebuild. Less structured than API extraction, but workable.
2. AI app builders (Bolt.new, v0.dev, Lovable, Replit Agent)
For non-developers:
- Export Drupal content to JSON/CSV using JSON:API or Views Data Export
- Upload to Bolt.new, v0.dev, Lovable, or Replit Agent
- Describe the site you want, referencing the exported content
- Iterate visually on the generated result
- Deploy or download the code
Best for simpler sites with a handful of content types and standard layouts. For complex Drupal sites with Paragraphs, many entity references, or custom View modes, a coding agent gives you more precision.
3. Hire a Drupal migration specialist
The Drupal community has a mature migration services market:
- Freelancers: $2,000-$10,000 for typical content site migrations. Drupal specialists understand entity architecture, Paragraphs, and field storage deeply.
- Agencies: $10,000-$50,000 for enterprise Drupal sites with complex content models, multilingual content, or deep integrations.
- Where to find them: Drupal.org marketplace, Drupal Slack (#migrations channel), Toptal, Upwork.
Worth considering for sites with complex Paragraphs content, multilingual setups (Content Translation or Entity Translation modules), custom entity types, or large content volumes (10,000+ nodes).
4. BrowserCat Migrate (automated)
BrowserCat Migrate is an automated service that crawls your Drupal site, extracts content and assets, and rebuilds it as a static site project deployed to Cloudflare Pages with a GitHub repo.
5. Drupal-native export tools
Drupal has the best content extraction ecosystem of any CMS:
- JSON:API (D8+ core): Full RESTful API for all entities. Supports relationships, filtering, pagination, and sparse fieldsets.
- Views Data Export (contrib): Export any View as CSV, JSON, or XML. Extremely flexible — if you can build a View for it, you can export it.
- Migrate module (D8+ core): Drupal’s own migration framework. Originally for D6/D7 to D8 migrations, but extensible to any source/destination.
- Default Content module (contrib): Export content entities as YAML/JSON. Good for smaller sites.
- Drush:
drush sql-dumpfor full database,drush sql-queryfor targeted exports, custom commands for entity exports.
These tools produce clean, structured data that any static site generator can consume.
6. Static site generator choice
Once your content is extracted, you need a static site generator. The main options:
| Generator | Best for | Build speed | Content model | Learning curve |
|---|---|---|---|---|
| Astro | Content sites, marketing, blogs | Fast | Built-in content collections with Zod schemas | Moderate |
| Hugo | Large sites (1000+ pages), fast builds | Fastest | TOML/YAML frontmatter, Go templates | Moderate |
| 11ty (Eleventy) | Simple sites, developer preference | Fast | Flexible (multiple template languages) | Low |
| Next.js (static export) | Sites needing some dynamic features | Moderate | Flexible (MDX, API, database) | Higher |
For most Drupal migrations, Astro is the most natural fit: its content collection system maps directly to Drupal’s content type concept, and it ships zero JavaScript by default.
7. Manual DIY
- Audit your Drupal site (content types, fields, taxonomies, Views, blocks)
- Export content using your preferred Drupal tool
- Choose a static generator
- Convert exported content to the generator’s content format
- Download files from
sites/default/files/ - Build layouts and components matching your existing design
- Implement listing pages to replace Drupal Views
- Configure URL redirects for SEO preservation
- Deploy to a static host (Cloudflare Pages, Vercel, Netlify — all free)
- Verify all pages, images, forms, and redirects
Drupal concepts mapped to static equivalents
| Drupal Concept | Static Equivalent | Notes |
|---|---|---|
| Content types | Collection schemas (Astro) or frontmatter conventions | Each type becomes a content directory |
| Nodes | Markdown/MDX files | One file per piece of content |
| Views (page listings) | Generated pages at build time | getStaticPaths() in Astro, list templates in Hugo |
| Taxonomy vocabularies | Frontmatter tags + generated term pages | Flat or hierarchical, depending on generator |
| Blocks | Reusable components | Header, footer, sidebar, CTA components |
| Paragraphs (nested content) | Components composed in MDX or structured data | Most complex mapping — each paragraph type becomes a component |
| Media entities | Files in public/ directory | Downloaded from sites/default/files/ |
| Menus | Navigation config files or components | JSON/YAML data consumed by nav components |
| URL aliases | Page routes or redirect rules | Critical for SEO preservation |
| Webforms | Static form handlers | Formspree, Netlify Forms, Basin, or serverless functions |
| Search | Client-side search (Pagefind, Lunr) or Algolia | Drupal Search / Search API replaced by JS-based search |
| Varnish/Redis caching | Not needed | CDN is the “cache” — always warm, no invalidation needed |
| Cron (scheduled tasks) | Build triggers or external cron | drush cron replaced by scheduled builds if needed |
When NOT to go static
Drupal is genuinely excellent software. Going static is the wrong choice if your site needs:
Complex permissions. “Editors in the marketing department can edit and publish articles. Regional managers can edit their region’s pages but need VP approval to publish. Interns can create drafts only.” Drupal’s role-based access control handles this natively. A static site has no concept of roles.
Editorial workflows. Content moderation with draft/review/publish states, scheduled publishing, revision comparison, content locking for concurrent editing. Drupal’s Content Moderation module (core in D8+) provides this. Static sites require external tooling.
Multilingual content management. Drupal’s Content Translation module with translation workflows, language negotiation, and locale-aware content is enterprise-grade. Mapping this to static site i18n is possible but loses the management interface.
Dynamic personalization. If content changes based on the logged-in user, their role, their location, or their history, you need server-side processing. Static sites serve the same HTML to everyone.
Complex entity relationships. If your content model depends on entity references that drive application behavior — events referencing venues, courses referencing instructors, products referencing categories with faceted filtering — Drupal’s entity system handles this elegantly. Replicating it in static generation is possible but requires more custom code.
Enterprise integrations. SSO/SAML authentication, LDAP directory integration, CRM sync, ERP connections via Drupal modules. These typically require server-side processing.
The Drupal community is protective of their platform for good reason. Drupal solves hard problems well. If your site uses those solutions, respect that and stay on Drupal. Going static makes sense when the site’s actual needs are simpler than what Drupal provides.
The Drupal to WordPress consideration
Some organizations consider WordPress as a middle ground — still a CMS with a browser-based editor, but with lower infrastructure requirements, a larger developer pool, and cheaper hosting. Drupal to WordPress is a well-trodden migration path with established tools and expertise.
This is a valid intermediate option if:
- Non-technical editors need a familiar CMS interface
- You want lower costs without going fully static
- Your content model is straightforward enough for WordPress
But if your end goal is minimal maintenance and maximum performance, going directly to static skips the intermediate step.
After the migration
Once your Drupal site is static:
- Hosting costs drop to zero. Cloudflare Pages, Vercel, and Netlify all offer generous free tiers for static sites.
- Maintenance becomes near-zero. No core updates, no module patches, no database backups, no PHP upgrades.
- Performance improves dramatically. Pre-built HTML from CDN edge nodes. Sub-50ms TTFB worldwide.
- Security surface disappears. No PHP to exploit, no SQL injection vectors, no Drupal SA (security advisory) to worry about.
- Developer requirements broaden. Any web developer can maintain a static site. AI coding agents can read and modify every file. You are no longer locked into the Drupal specialist market.
- Content editing options exist. If you need a browser-based editor, add Decap CMS (free, Git-backed), Tina CMS, or a headless CMS like Sanity or Contentful. These provide an editing UI without Drupal’s infrastructure.
The trade-off is real: you lose Drupal’s polished editing experience, its module ecosystem, and its built-in content management features. For content sites that do not use those features, the trade is overwhelmingly favorable. For sites that do, Drupal remains the right tool.
Automate Everything.
Tired of managing a fleet of fickle browsers? Sick of skipping e2e tests and paying the piper later?
Sign up now for free access to our headless browser fleet…