What Finally Got Me Off WordPress
- 05 Oct, 2026
Every site I built between 2018 and 2025 was on WordPress. I started in 2018 when I founded Jumeni, and back then, next to hand-rolling something in React or Angular, WordPress was just faster. Hundreds of plugins, templates, and site builders already existed for almost anything a client wanted. I built sites for people, launched landing pages for my own ideas, and WordPress was the obvious tool every time.
All of it was self-hosted. I’d grab a cheap VPS, install PHP-FPM, Nginx, and MySQL, and stack sites on top of the same box. Writing a custom PHP function to do something a plugin couldn’t was never the hard part. The hard part showed up later, in five different shapes, over and over, for seven years.
Malware you can’t fully clean by deleting files
I hosted a site for a client who uploaded a nulled WordPress theme. A few days later, the site was redirecting visitors to porn and gambling ads. I cleaned it up. It came back within hours.
Whoever cracks a theme to sell or distribute it for free usually plants a backdoor in it first, that’s the business model. The backdoor is typically obfuscated PHP, something like eval(base64_decode(...)), sometimes a full web shell, and it gives the attacker arbitrary code execution on the server, not just access to that one site. My sites ran under the same Linux user on the same VPS, so the backdoor could write to every file it had permission to touch, including project folders that had nothing to do with WordPress.
Deleting the files didn’t fix it because the infection wasn’t only in the files. Backdoors commonly write into the database too, injecting redirect logic into wp_options or creating a hidden admin user in wp_users. Clean the files, leave the database alone, and the site rewrites the files right back on its next page load, which is exactly what I watched happen. The actual fix was a full rebuild of every site, a database audit, and isolating each site to its own Linux user so one compromised site couldn’t reach the others.
After that I put Cloudflare in front of everything and started watching the scan and probe traffic hit my sites. It’s constant. WordPress gets targeted at a volume that’s hard to appreciate until you’re the one watching the logs, which is also why a government website running an outdated WordPress plugin shows up in the news every so often.
Plugins solve one problem and create three more
A plugin is a reasonable way to add a feature until you’re running enough of them to notice the resource cost. Finding the right plugin could eat an entire afternoon, and the one that actually did what I needed was usually paywalled behind a premium tier, broken on whatever WordPress version I was running, or close enough that I’d still end up patching it myself. Once installed, every plugin needed updating indefinitely, and updates broke things often enough that I got used to keeping a rollback plan ready before I touched any of them.
Themes outlive the people who built them
Design isn’t my strength, I’m a backend person, so I usually bought a theme or built with Elementor rather than design a UI from scratch. Most of the projects I took on weren’t worth the time a real UI/UX pass would have cost, and most clients weren’t paying for one either.
The problem shows up years later. A theme developer stops supporting what you bought and moves on to their next one, and when something breaks on a site that’s been running for three years, you’re reverse-engineering code nobody maintains anymore. Other times the theme looked great and the code underneath it was trash from day one, you just hadn’t hit the part that would show you that yet.
Every page load is a trip to the database
WordPress renders dynamically by default: every request runs PHP, which queries MySQL for the content, options, menus, and widgets that page needs. There’s no static HTML sitting around unless something puts it there. I spent a lot of time on page load optimization, and the honest fix usually wasn’t optimization, it was caching, a plugin whose entire job is pretending the page is static so the database doesn’t get hit on every visit. The fact that a whole category of plugin exists just to work around this is itself the evidence that the default architecture is the problem.
Moving providers means moving everything by hand
I switched VPS providers a handful of times, usually chasing cost. Each move meant migrating the database, the configs, the files, and anything else that made the site work. Migration plugins exist, but the ones that actually work well enough to trust aren’t free, and I wasn’t paying for a tool to do something I could technically do myself. So I did it by hand, every time, for every site. Nobody made me do this. I still hated it, because WordPress has enough moving pieces that nothing about the process ever got easier the second or third time.
Finding Astro
I saw a post about Astro on X and had never heard of it before. Most of what I’d built was content: no interactive backend, no reason to run PHP-FPM or any server process at all. I already write Markdown constantly like any other developer, and Astro’s whole model is content as files, no database required for a site that’s fundamentally content.
Astro still supports interactive pieces when something actually needs them, through what it calls islands: you can drop in a React, Vue, Svelte, or Alpine component next to plain static markup, and only that one component ships JavaScript to the browser and hydrates. Most of the page stays static by default.
The part that mattered most practically: free hosting. I could decommission a VPS entirely and host on Cloudflare Pages at no cost. Every problem on my list up to that point, malware surface, plugin sprawl, theme rot, database-per-request latency, migration pain, came from running a dynamic, database-backed, plugin-dependent system myself. Astro sidesteps the category by not being that kind of system in the first place. Node modules replace plugins, and I’d take that trade every time.
Why AI tipped it the rest of the way
AI-assisted coding is the biggest reason I actually moved, more than any of the above. Tools like Claude Code work on files and git history: they read code, edit it, and show you a diff. WordPress content and Elementor’s page-builder output live in the database as serialized state, not files. Elementor does have its own history feature for its page builder, and I never fully understood how it worked or trusted it enough to rely on it. Astro’s content is markdown files and components sitting in a repository I already know how to version with git.
Changing something on WordPress, swapping a slider, adjusting a layout, used to take real mental effort to locate and change safely. On Astro, when I actually want AI’s help with a change, it fits into the same git workflow I already use for everything else, instead of being its own separate, fragile process.
A few sites in
The first thing I migrated was jumeni.com, the startup I had back in Ghana. I did the whole migration in one Saturday afternoon. The site went from a couple of seconds to load to instant, and it stops being something that can go down just because I’m making a change on a server, because there’s no server running it anymore.
The second was jabbco.ca, a property site I offered to build for my landlord specifically to test where Astro’s limits are for something that needs a bit of backend. That’s its own story for another time.
This site, eyramm.com, runs on Astro too. If you’re reading this, you’re already looking at the result.
A few months after I started using it, Cloudflare acquired The Astro Technology Company outright and committed to keeping it open source, with Astro’s own team saying it’ll stay “the best way for developers to build content-driven websites, whether they host on Cloudflare or elsewhere.” Not every framework survives long enough to get acquired instead of abandoned, and I was already bullish on Cloudflare as a product I use constantly. That’s one more reason to trust the bet I’d already made.
