Why I Left WordPress (and Dodged a PHP Zero-Day)
I’ve always enjoyed tinkering with my web stack to stay on top of how modern technologies and developer workflows evolve. Seven years ago, I wrote about migrating this site from shared hosting to an AWS Lightsail VPS with Let’s Encrypt. That Bitnami WordPress setup was a faithful workhorse for the better part of a decade.
Recently, though, I’ve been wanting a change.
It wasn’t just about aesthetics; it was structural. In my work, I found myself increasingly inspired by the interactive artifacts — calculators, reactive charts, etc. — that modern AI coding agents could generate. But trying to embed bespoke interactive code inside a WordPress block editor was like trying to fit a jet engine into a chariot. While it was possible (i.e. through <iframe>s), WordPress was simply not meant for this type of customization. And it locked everything inside MySQL database tables.
So I decided to pull the plug on WordPress and rebuild the site from the ground up using Astro 5 hosted on Cloudflare Pages and with a fair amount of help from AI.
Here is why I made the switch, the architectural choices along the way, and how the timing accidentally spared me from an emergency cybersecurity scramble.
The Push: Governance Drama and Attack/Upgrade Surface
Three factors led to my decision to leave WordPress behind.
The first was the broader operational and security friction inherent to running a PHP content management system like WordPress. A self-hosted WordPress deployment means running an unmanaged Linux server with an active PHP runtime and a database directly exposed to the public internet. That stack requires continuous work: applying patches and updates (as PHP is frequently attacked), managing Let’s Encrypt renewal and troubleshooting the occasional DNS issue, and auditing third-party plugins.
Compounding that maintenance burden, Bitnami — following its acquisition by Broadcom — walked away from providing upstream updates for its AWS Lightsail WordPress blueprints. While AWS has since rolled out its own native WordPress replacement blueprints, moving off the deprecated Bitnami stack still would have required a painful instance migration. If I was going to endure a migration, it made sense to rethink the foundation.
The final push came from Automattic, the company behind WordPress, and its leader Matt Mullenweg. A sequence of recent controversies surrounding WordPress — most notably Automattic’s escalating legal war with WP Engine, the unprecedented forced repository takeover and renaming of Advanced Custom Fields (ACF), and the introduction of mandatory loyalty checkboxes on the WordPress.org login screen — made the platform feel uncomfortably volatile. It wasn’t just one isolated misstep, but a pattern of weaponizing core community infrastructure. For me, relying on a centralized ecosystem subject to such unilateral misbehavior felt like an unnecessary liability. I wanted out of WordPress.
Architectural Choices: Why Astro + Cloudflare Pages?
Rather than just swapping out one CMS for another, I treated the migration as an opportunity to modernize the entire stack from top to bottom. What I arrived at was a meaningful departure from what came before. Moving to Astro and Cloudflare Pages meant rethinking every layer: the infrastructure (always-on VPS vs. serverless platform), the runtime (PHP vs. static pre-rendering), storage (VPS disk vs. Cloudflare R2), the content engine, and web distribution (Cloudflare’s edge network vs. a single AWS Lightsail instance sitting in one region).
- Origin:
- Single Ubuntu Linux VPS (Fixed AWS Region)
- Runtime:
- Apache + PHP 8.x + MySQL Monolith
- Storage:
- Local disk with redundant auto-thumbnails
- Content:
- MySQL tables via WYSIWYG block editor
- Edge CDN:
- 300+ Cities Globally (Sub-50ms TTFB)
- Runtime:
- Zero Server Runtime (Pre-rendered HTML)
- Storage:
- Cloudflare R2 (WebP originals, $0 egress)
- Content:
- Git Content Collections (MDX + Astro Embeds)
| Stack Layer | Legacy: Monolithic VPS (AWS Lightsail, 2019–2026) | Modern: Serverless Edge (Astro 5 + Cloudflare Pages) |
|---|---|---|
| Origin / CDN | Single Ubuntu Linux VPS (Fixed AWS Region) | 300+ Cities Globally (Sub-50ms TTFB) |
| Runtime | Apache + PHP 8.x + MySQL Monolith | Zero Server Runtime (Pre-rendered HTML) |
| Storage | Local disk with redundant auto-thumbnails | Cloudflare R2 (WebP originals, $0 egress) |
| Content | MySQL tables via WYSIWYG block editor | Git Content Collections (MDX + Astro Embeds) |
1. Serverless Edge, Custom Integrations, and Zero Maintenance
Instead of spinning up another virtual machine on AWS Lightsail or DigitalOcean to serve Node or Docker containers, I opted for a serverless deployment on Cloudflare Pages.
The practical benefits were immediate:
- Zero server maintenance & global CDN distribution: There are no operating systems to patch, no background daemons to hang, and no SSH keys to manage. Every page is automatically replicated and cached across Cloudflare’s global edge network rather than served from a single un-replicated VPS.
- Generous free-tier economics & media hygiene: Cloudflare’s free tiers across Pages, Workers, D1, and R2 easily match the traffic profile of a personal blog, eliminating a 24/7 monthly compute bill for a mostly idle server. Along the way, I pruned thousands of redundant thumbnail variations that WordPress generated over the years, compressed the master images to WebP, and moved them to Cloudflare R2 for more modern and performant image serving.
- Lightweight custom integrations: Leaving a monolithic CMS meant replacing a few built-in features with cleaner, modular alternatives. For the email newsletter, I removed Jetpack and wired the build pipeline and full-content RSS feed to Buttondown (note for reader-subscribers: that’s why your latest subscription is coming not from WordPress Jetpack now). For reader comments, I built a lightweight serverless endpoint using Cloudflare Pages Functions backed by Cloudflare D1 (an edge SQLite database), gated by Cloudflare Turnstile and Zero Trust SSO for moderation.
2. Static Generation, Performance, and Composable Interactivity
Switching the frontend to Astro and MDX improved both performance and creative flexibility at once.
By default, Astro pre-compiles every article into flat static HTML at build time, making standard reading pages load almost instantaneously. Yet whenever an essay benefits from interactivity, MDX lets me import and embed custom UI components directly — with full control over design, state, and layout that a CMS WYSIWYG editor could never support, but which AI coding assistants make it much easier to build.
A clear example where this made a huge difference is my Why is it so Hard to Build a Diagnostic Business? essay. In the original WordPress version, explaining why high-accuracy screening tests often suffer from surprisingly low Positive Predictive Values (PPV) required static screenshots, awkward <iframe>s and external links. With Astro, readers can now adjust test sensitivity, specificity, and disease prevalence sliders directly inside the article using embedded clinical and economic calculators to help convey the point of the post.
3. The Power of a Git-Backed, AI-First Corpus
By using Astro Content Collections, this entire webpage — every essay, reading note, and portfolio piece — now lives in a single Git repository as plain Markdown and MDX files.
This brings two major advantages:
- Full Version Control: Every typo fix, structural edit, and component update is tracked in atomic Git commits with clear diffs and instant rollback capability.
- AI Tooling Synergy: Because the entire archive lives in one local codebase rather than inside opaque MySQL database tables, AI coding tools can search, distill, cross-reference, and refactor the whole blog. Changing formatting, auditing broken links, and building new interactive widgets went from tedious manual work inside WordPress to fast, agent-assisted workflows.
4. Why I Passed on Cloudflare’s Emdash
During the planning phase, I also seriously evaluated Emdash — Cloudflare’s open-source CMS built natively for Astro on top of Workers, D1, and R2. Emdash is an ambitious project that positions itself as a modern spiritual successor to WordPress, complete with sandboxed plugin isolates (historically a major source of security vulnerabilities for WordPress).
Ultimately, I decided not to go with it for two reasons. First, Emdash is still very young, and its relative immaturity felt a little scary to adopt when my goal was long-term simplicity. Second, and more fundamentally, adopting Emdash meant buying back into the mental model of a dynamic CMS with an administrative database and runtime abstraction layers.
I didn’t want another CMS. I wanted a directory of text files and code.
Why Astro Matters Here (A Slightly Gratuitous Demo): The interactive scroll-driven breakdown below is a somewhat gratuitous demonstration of the kind of bespoke experience that would have been a nightmare to build and maintain inside a traditional CMS like WordPress. It was also pretty simple to put together with AI coding tools.
Interactive Architecture Breakdown: On the web, this section features an interactive scroll-driven diagram comparing the old and new stacks across four pillars (view the live interactive experience on benjamintseng.com →). Below are the four pillars:
Why Change the Architecture
Scroll through the four pillars below — or click the tabs — to see how the stack changes across infrastructure, security, cost, and authoring experience.
Why Host, Use Cloudflare’s Global Network
The worst parts of VPS administration revolved around security, networking, and updates. Going serverless eliminates that entirely, while also upgrading web distribution from a single un-replicated AWS Lightsail box to Cloudflare’s global edge network across 300+ cities with built-in caching and DDoS protection.
Serving Static HTML, Not PHP
PHP and its plugin ecosystem are constantly hammered by hackers and automated vulnerability scanners, requiring regular security updates (as the recent PHP2Shell zero-day showed). With Astro on Cloudflare Pages, there is no PHP, no server-side code to render posts — just pre-built static HTML.
Generous Cloudflare Free Tiers
With a traditional VPS, you pay a fixed monthly compute bill 24/7 even when nobody is reading your site. Cloudflare’s free tiers across Pages, Workers, D1, and R2 easily cover a personal blog’s traffic at $0/month, and pruning WordPress’s auto-generated image thumbnails into compressed WebP keeps storage lean.
Interactive Components & AI-Ready Repo
Storing the entire blog as plaintext .mdx files in a single Git repository means version-control and easy access for AI tools. Astro’s component model also makes it trivial to create custom layouts and bespoke visualizations inside an essay (like this scroll-experience).
A Funny Coincidence: Dodging PHP2Shell
There is one final footnote to the migration that felt like a stroke of poetic timing.
Just days after I migrated to Cloudflare Pages, security researchers publicly disclosed PHP2Shell (CVE-2026-109618 / CVE-2026-109619).
The vulnerability is a critical pair of unauthenticated Remote Code Execution (RCE) flaws in the core PHP parser with a CVSS severity of 9.2. Because it exploits memory corruption before application-level code or authentication logic even executes, an attacker can compromise a vulnerable server simply by interfacing with it over the internet!
Had I still been running that Bitnami WordPress instance on Lightsail, I would have had to SSH in, migrate to the new AWS Lightsail WordPress stack, upgrade PHP packages, and verify nothing broke. Instead, because Astro pre-compiles every post into flat static HTML at build time, there is literally no PHP or server to attack. I narrowly dodged one of the worst PHP security issues in history days before the vulnerability was even announced.
Looking Ahead
Web publishing doesn’t have to be limited to passive columns of text. While I’m not going to turn every essay into a software application, having the flexibility to embed interactive models, reactive charts, and bespoke presentations when the topic calls for it makes writing on the web fun and exciting again.
If you notice any broken links or visual quirks as a result of the cutover, feel free to leave a note below — the comment section now runs on serverless Cloudflare Pages Functions and an edge-native SQLite database (Cloudflare D1), free of third-party tracking scripts.
Here’s to cleaner code and (hopefully) more interesting content ahead.
Stay updated via email
Get new essays on healthcare, biotechnology, operational models, and curated reading directly in your inbox.
Discussion
Moderated for qualityLeave a Comment
Your email address is never published. Comments are approved manually before appearing.