• Essay

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 wanted a change.

It wasn’t just about aesthetics. In my day-to-day work, I found myself increasingly inspired by the interactive artifacts (calculators, reactive charts, parameter sliders) that modern AI coding tools can 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 technically possible using messy <iframe>’s, WordPress was simply never built for that kind of customization. Worse, it locked every post and revision away inside MySQL database tables, making it difficult to edit posts or glean text from multiple at once (without just opening many browser tabs).

So I decided to pull the plug on WordPress and rebuild the entire site from scratch using Astro 5 hosted on Cloudflare Pages (with a fair amount of help from AI coding agents along the way).

Here is why I made the switch, the architectural choices underneath it, and how I inadvertently managed to avoid a (frightening) PHP Zero Day by doing so!


The Push: Governance Drama and the Attack/Upgrade Surface

Three distinct factors pushed me to leave WordPress behind.

First was the ongoing annoyances of running a PHP content management system (CMS). A self-hosted WordPress deployment means maintaining an unmanaged Linux server with an active PHP runtime and a database exposed directly to the public internet. Such a stack demands some babysitting: applying security patches (as PHP and its vast plugin ecosystem are relentless targets of hackers), debugging Let’s Encrypt renewal errors when certificates expire, and auditing third-party plugins.

Second, Bitnami (following its acquisition by Broadcom) quietly walked away from providing upstream updates for its AWS Lightsail WordPress blueprints. While AWS eventually rolled out its own WordPress blueprints, moving off the deprecated Bitnami image would have required a painful, manual server migration anyway. If I was going to spend a weekend doing that, it made sense to rethink the underlying foundation.

The final push came from governance and ecosystem drama at Automattic, the company behind WordPress. A sequence of controversies surrounding WordPress and its CEO Matt Mullenweg — 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 page — made the platform feel like it had lost its way. When core technology infrastructure becomes a political weapon to be wielded in a commercial dispute, it ceases to be a reliable ecosystem, but a risky dependency. I didn’t want my personal writing platform dependent on the whims of a centralized ecosystem. I wanted out.


Architectural Choices: Why Astro + Cloudflare Pages?

Rather than just swapping one CMS for another, I used the migration to re-architect the site from first principles.

Moving to Astro and Cloudflare Pages fundamentally shifted every layer: the infrastructure (always-on VPS vs. serverless edge), the runtime (PHP vs. static pre-rendering), media storage (VPS-attached disk vs. Cloudflare R2), and web distribution (a single AWS Lightsail instance in one region vs. Cloudflare’s global edge network).

Legacy: Monolithic VPS (2019–2026) AWS Lightsail
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
Modern: Serverless Edge (Astro 5) Cloudflare Pages
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)
Architectural transition from a single-origin LAMP stack on AWS Lightsail to pre-rendered static edge assets on Cloudflare.

1. Serverless Edge, Custom Integrations, and Zero Maintenance

Instead of spinning up another virtual machine on AWS Lightsail or DigitalOcean to host Node or Docker containers, I opted for a serverless deployment on Cloudflare Pages.

The practical benefits were immediate:

  • Zero server maintenance and global distribution: There are no operating systems to patch, no background daemons to crash, and no SSH keys to manage. Every page is pre-compiled at build time and cached across Cloudflare’s worldwide network rather than served from a single, un-replicated VPS.
  • Generous free-tier and media hygiene: Cloudflare’s generous free tiers across its Pages, Workers, D1, and R2 products easily handle a personal blog, eliminating a monthly compute bill for what is mostly an idle server. During the cutover, I took advantage of the transition and pruned thousands of redundant, automatically generated WordPress thumbnails, compressed all master images to the modern WebP format, and offloaded them to Cloudflare R2 for more performant image serving.
  • Lightweight custom integrations: Leaving a monolithic CMS meant replacing some WordPress / plugin functionality with modular alternatives. For the email newsletter, I ditched Jetpack and wired my build pipeline directly to Buttondown (which is why subscriber emails now come through Buttondown rather than WordPress). For reader comments, I built a lightweight serverless endpoint using Cloudflare Pages Functions backed by an edge SQLite database (Cloudflare D1), secured by Cloudflare Turnstile to block bot-spam.

2. Static Generation, Speed, and Composable Interactivity

Switching the frontend to Astro and MDX improved both performance and creative flexibility at once.

By default, Astro compiles every article into flat, static HTML with minimal client-side JavaScript. Essays and posts load almost instantaneously. But whenever an essay calls for interactivity, MDX lets me import and embed bespoke UI components directly. I get total control over component layout, styling, and reactive state — things a standard CMS editor could never handle gracefully, but which modern AI coding tools are great at (or at least far better than I am).

A clear example of this is my deep dive on Why is it so Hard to Build a Diagnostic Business?. In the original WordPress version, explaining why high-accuracy screening tests suffer from surprisingly low Positive Predictive Values (PPV) required static screenshots, awkward <iframe> embeds, and external spreadsheet links. With Astro, I can embed interactive sensitivity, specificity, and disease prevalence sliders directly in the page so readers to see the math play out in real time on embedded clinical and economic calculators.

3. Git-Backed, AI-Ready Corpus

With Astro Content Collections, my entire writing archive — every essay, reading note, and portfolio project — now lives in a single Git repository as plain Markdown and MDX files.

This has two advantages:

  1. Version control: Every typo fix, structural edit, and component tweak is tracked in atomic Git commits with clean diffs and instant rollback capability.
  2. AI tooling synergy: Because the entire archive lives locally in text files rather than inside opaque MySQL tables, AI coding tools can search, analyze, cross-reference, and refactor the entire blog at once. Auditing links, reformatting, and building new interactive widgets went from tedious chores inside a clunky WordPress admin page to AI-assisted workflows.

4. Why I Passed on Cloudflare’s Emdash

During the planning phase, I also evaluated Emdash, Cloudflare’s open-source CMS built natively for Astro on top of Workers, D1, and R2. Emdash is an ambitious effort to build a modern “spiritual successor to WordPress”, complete with sandboxed plugins (historically the primary vector for WordPress security vulnerabilities).

Ultimately, I decided against it for two reasons. First, Emdash is still in its infancy, and adopting an early-stage CMS contradicted my primary goal of long-term simplicity. Second, adopting Emdash also meant buying back into the CMS mindset with an admin dashboard, a database, and a server runtime.

But, I didn’t want a “better” 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.

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.

AWS LIGHTSAIL VPS Single-Region Origin Monolithic LAMP OS & PHP daemons to patch No Edge CDN Every visitor hits 1 origin SINGLE FAILURE POINT Server reboot = site offline CLOUDFLARE PAGES Serverless & Global Edge Zero Server Maintenance No OS, no daemons, no downtime Americas Europe Asia-Pac 300+ Edge Locations Sub-50ms Global Hits & DDoS Shield WEB TRAFFIC Inbound Requests PHP Scanners RCE Zero-Days Reader Visits WORDPRESS: LIVE PHP RUNTIME Dynamic code execution on every visit HIGH EXPLOIT SURFACE Vulnerable to RCE zero-days (e.g. PHP2Shell) ASTRO: STATIC HTML FILES ONLY Pre-built files served directly from edge storage 0 SERVER-SIDE ATTACK SURFACE No PHP • No WordPress Database • Nothing to Exploit Comments isolated in Cloudflare D1 FIXED VPS BILLING Always-on compute expense ~$5 – $10 / mo Idle Compute Cost Billed 24/7 even when zero readers are online WordPress Media Bloat 4–6 auto-sized thumbnails per uploaded image $0 CLOUDFLARE FREE TIERS Zero-dollar baseline for personal blog $0.00 / month CF Pages Unlimited Hits CF Workers 100k Req/Day D1 SQLite 5 GB Free R2 Storage 10 GB + $0 Egress 419 WebP Assets on R2 Eliminated redundant WP thumbnails GIT + MDX CORPUS Plaintext Repository Version Control Atomic Git commits & diffs Local editing in VS Code No opaque MySQL database AI Coding Agents One flat directory for LLMs Search & edit across posts Rapid prototyping of UI COMPOSABLE MDX Astro Component Model <ClinDxCalculator /> Interactive PPV / NNS sliders embedded directly in essay body <ArchitectureEvolution /> Bespoke scroll-driven SVG stage no CMS plugin boundaries Full Design Control Tailwind CSS, KaTeX math, D3 & SVG
Serverless & Edge CDN

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.

Distribution: 300+ Edge Locations
Static Security

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.

PHP Attack Surface: 0 (HTML only)
Cost-Efficiency

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.

Media: 419 WebP Assets on R2
Composability & AI

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).

Stack: Composable MDX + Git + AI

A Lucky Coincidence: Dodging PHP2Shell

There was one final footnote to the migration that was incredibly lucky. Just days after I finished migrating 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. Because it exploits memory corruption before application-level code or authentication logic even executes, an attacker can compromise a vulnerable server simply by sending a request to an affected server 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 its PHP packages, and verify nothing broke. Instead, because Astro pre-compiles every post into static HTML at build time, there is literally no PHP runtime or server to worry about. I inadvertently dodged one of the most severe PHP zero-days in history simply by migrating a little earlier.


What’s Next

Web publishing doesn’t need to be confined 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 spot any broken links or layout quirks from the cutover, feel free to leave a note below — the comment section now runs on serverless Cloudflare Pages Functions and an edge SQLite database (Cloudflare D1).

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.

Zero spam. Syndicated directly via Buttondown. Unsubscribe anytime.

Discussion

Moderated for quality
Loading comments...

Leave a Comment

Your email address is never published. Comments are approved manually before appearing.