I have built WordPress sites. Properly built them, not just clicked around in the admin. Themes written from scratch, custom post types, ACF field groups, the lot. I have also been handed a fair number of other people's WordPress sites after they were compromised and asked to clean them up, which teaches you a different set of lessons entirely.
In thirteen years of working in Umbraco, I have never once had to clean up a hacked Umbraco site. Not one. I will come back to why that is, because the reason isn't the one you might expect.
Since 2013 I have worked almost exclusively in Umbraco. This post explains why.
It is biased. I run an Umbraco agency, so of course it is. But I am not interested in pretending WordPress is rubbish, because it isn't, and anyone who says otherwise has usually never shipped anything on it.
The short version
WordPress is built to get a site live quickly and cheaply, with a vast ecosystem filling in whatever the core doesn't do. Umbraco is built so that the thing you deliver is still maintainable in five years.
Different goals. Which one you want depends on the project, and I have recommended both.
Security
The problem isn't WordPress core
This is the bit most people get wrong, usually the people trying to sell you something. WordPress core is well hardened these days.
Patchstack's State of WordPress Security in 2026 logged 11,334 new vulnerabilities across the WordPress ecosystem in 2025, up 42 per cent on the year before. Six of them were in core, all low risk. Around 91 per cent were in plugins.
So the CMS isn't the problem. The supply chain around it is.
Plugins are dependencies you don't control
Every plugin you install is a maintenance commitment made by someone else, on their timescale, with their standards. The same Patchstack report found 46 per cent of vulnerabilities had no vendor fix available when they went public, and the median gap between disclosure and mass exploitation is now measured in hours.
Think about what that means on a site with twenty plugins. Roughly half the time, the exploit is public and there is nothing to patch. You are relying on a WAF, virtual patching, or luck.
I have cleaned up sites where the entry point was a plugin the client installed themselves eighteen months earlier, used once, forgot about, and never updated. The author had abandoned it. Nobody noticed until the site started serving pharmacy spam to Google.
What changes with Umbraco
Nothing magic. It is structural.
The Umbraco package ecosystem is a fraction of the size, so the attack surface is a fraction of the size. More to the point, a typical Umbraco build solves its problems with code we wrote. A bespoke form handler or a custom integration has no public CVE feed, because it isn't installed on a hundred thousand other sites. Bots scan for known plugin signatures at scale. There is nothing there to find.
There is also less exposed by default. No login path every bot on the internet already knows. No theme layer executing PHP on the front end. The back office can sit behind IP restrictions or Entra ID without needing a plugin to do it.
Umbraco isn't magic
Back to the point I opened with. I have never had to clean up a hacked Umbraco site, but that isn't because Umbraco is bulletproof. It's partly that there's less lying around to be found, and partly that Umbraco sites tend to have somebody looking after them, because they were built by somebody in the first place. Nobody self serves an Umbraco install and then forgets about it for three years.
Umbraco has had its own advisories, and it will have more. An Umbraco 8 site sat unpatched since 2023 is every bit as exposed as an unpatched WordPress site. The difference is you're tracking one product's security releases instead of twenty, which is a job a human being can actually do. That is most of what our maintenance and health check work consists of.
And to be fair to WordPress: a site with five well chosen plugins, auto updates on, a WAF in front and a decent managed host is a secure website. Those exist. They're just not the average, and the average is what you inherit.
Compiled code and the stack
It breaks on my machine, not the client's homepage
Umbraco runs on ASP.NET Core. The site is compiled C# on the .NET runtime. WordPress is interpreted PHP. The speed difference matters less than people think. The build time difference matters far more.
Rename a property on a document type and forget to update a view, and the build fails while I'm sat at my desk. Do the equivalent in PHP and you find out when a page white screens in production on a Friday afternoon.
With ModelsBuilder and strongly typed models, the compiler knows what a page is, what properties it has, and what each one returns. Refactoring a large site becomes a mechanical job rather than a search across the codebase followed by crossed fingers.
Hooks versus dependency injection
WordPress extensibility runs on hooks and filters. It's clever, and it's why the ecosystem got so big, but there is no contract. Anything can hook anything. Behaviour emerges from whatever combination of plugins happens to be active, which is why WordPress debugging so often starts with deactivating things one at a time until the problem goes away.
Umbraco uses DI, interfaces and notification handlers. You register your services, you can see what's registered, and you can unit test it. On a build with real integrations and real business logic, that's the difference between a system and a pile of extensions.
Content modelling
Document types, compositions and block editors are core Umbraco, not a bolt on. Multilingual is built in through variants rather than sitting on top of WPML or Polylang and hoping.
ACF is genuinely good, and I'd rather have it than not. But it's a plugin doing a job the CMS should be doing, and everything downstream of it inherits that.
Performance
What actually happens on a page request
Umbraco keeps the published content cache in memory, so rendering a page is usually a memory read and a Razor render. Umbraco 17 sits on .NET 10, which brings another round of runtime improvements for free.
A stock WordPress request bootstraps core, loads every active plugin whether the page needs it or not, then queries posts and postmeta. It's why so much WordPress performance work is really caching plugin configuration work. You're adding a layer to hide the cost rather than removing it.
Scaling
Umbraco load balances properly across instances, and from v17 the back office does too, which matters if you've got a large editorial team. Put Front Door or Cloudflare in front and the scaling story is predictable.
Where this argument falls down
A well built WordPress site on a good caching layer will comfortably beat a badly built Umbraco site. Architecture sets the ceiling, it doesn't guarantee the result.
I've seen Umbraco sites brought to their knees by someone hitting the database on every render. I wrote about tracking down that sort of thing on Umbraco Cloud because it happens often enough to be worth documenting. The platform doesn't save you from yourself.
Page bloat
This is the one clients notice without being told.
A typical WordPress build inherits markup from a theme written to satisfy thousands of different buyers, plus a page builder wrapping everything in nested divs, plus every active plugin injecting its own CSS and JS into the head globally. Thirty odd requests before any real content renders, most of it for features that page doesn't use.
There's no theme layer in Umbraco and no page builder generating markup on your behalf. You write the HTML. If a page needs one stylesheet and one script, that's what it ships.
Where this bites is Core Web Vitals. Getting good LCP and CLS on a lean hand built front end is straightforward. Retrofitting them onto a page builder site carrying a dozen plugin assets is its own project, and more often than not the honest answer is a rebuild, which is a conversation nobody enjoys. It's why Umbraco SEO work tends to start with the markup rather than the meta tags.
In fairness, this is a choice rather than a rule. A hand coded WordPress theme with no page builder produces clean output. It's just that hardly anybody builds them that way any more.
Packages and the community
NuGet beats an install button
Umbraco packages are NuGet packages. They're versioned dependencies declared in the project file, restored at build, and they go through source control and the deployment pipeline like everything else. Nobody installs one on production by clicking a button in the admin panel. That's a feature.
The ecosystem is much smaller than WordPress's sixty thousand plus plugins, and I'm not going to spin that as an advantage in every direction. There genuinely is less off the shelf, and sometimes you write it yourself. I've released a few packages myself for exactly that reason, most recently ImageSharp TrimCache.
What you do get is packages maintained by people who are visible, contactable and generally on Discord. And no upsell banners in the back office.
The community
Umbraco's community is small enough to actually know. Ask a question and there's a fair chance the person answering wrote the code. Codegarden, the awards, the MVP programme, the local meetups including the Kent one I help run. You take part in it rather than just consume from it.
WordPress has scale, and scale is worth something real. Whatever problem you've hit, someone has blogged about it. There are more developers, more agencies, more freelancers. If you needed to replace your agency next month, the WordPress talent pool is far deeper than the Umbraco one. That's a legitimate business risk and I'm not going to wave it away. It's part of why we offer white label work to other agencies, because the pool of people who can actually do this is small.
Hosting
Umbraco runs cross platform on .NET. Linux or Windows, IIS or Kestrel, containers, App Service, all fine. SQL Server for anything serious, SQLite for the very small stuff. Umbraco Cloud is there if you want HQ handling the infrastructure and upgrades, with a Git based workflow across local, dev and live that is genuinely good.
WordPress wins outright at the bottom end. There's an entire industry of five quid a month shared PHP hosting and there is no .NET equivalent. If the budget is that tight, that gap is real and pretending otherwise is daft.
Higher up it flips. Once you're paying for managed WordPress hosting, a security subscription, premium plugin licences and a staging environment, you're spending real money. An App Service and an Azure SQL database is competitive at that point, and you get infrastructure as code, deployment slots and proper monitoring with it. If you'd rather run it yourself, I've written up setting up Windows Server 2025 for Umbraco.
Upgrades and lifecycle
Umbraco's release cadence is published and tied to .NET. Two majors a year, every fourth is LTS, LTS gets three years. Umbraco 17 is current, built on .NET 10, supported until November 2028. Umbraco 13 goes end of life in December 2026, and there's a direct 13 to 17 upgrade path, which I've written up in detail.
The value there is that a client can budget an upgrade two years out because the dates are known. No guesswork.
WordPress upgrades are easier day to day. Core updates are largely automatic and rarely break anything. They're harder over the long run, because the risk lives in thirty plugin dependencies on thirty separate schedules, any of which can be abandoned with no notice and no migration path. Planning a WordPress site's next five years is much more difficult than planning an Umbraco one's, which is most of what migration work turns out to be about.
Cost
Umbraco costs more up front. The CMS itself is free and MIT licensed, but you're commissioning a build rather than configuring a theme, and .NET day rates are what they are. Forms, Commerce, Deploy and Engage are commercial add ons on top.
The return shows up later in lower maintenance overhead, fewer emergencies and a site you can extend without fighting it. Whether that trade is worth making depends on how long the site needs to live and what it costs you when it falls over.
When I’d tell you to use WordPress
I'm not going to put someone on Umbraco just because I prefer it. WordPress is the better call when:
The budget is small and the requirement is a brochure site or a blog.
The client wants to self manage everything and has no development partner.
The requirement maps cleanly onto something that already exists. A straightforward WooCommerce shop, a standard membership site.
The in house team already knows WordPress and there's no appetite for retraining.
Launch date matters more than anything else.
When Umbraco is the right call
Security or compliance is a real requirement rather than a box to tick. Public sector, healthcare, finance, anything regulated.
The site has to talk to line of business systems. CRM, ERP, internal APIs.
The organisation is already a Microsoft shop on Azure and Entra ID.
Content modelling is awkward. Multiple sites, multiple languages, editorial workflow that doesn't fit a standard shape.
The site needs to live and evolve for five or ten years.
Performance is a business requirement rather than a wish.
My verdict
The question isn't which CMS is better, it's what you're actually building.
If you need a website, WordPress will get you one faster and cheaper, and I'd say so. If you need a system that happens to have a website attached, and you want it to still make sense once the people who built it have moved on, Umbraco's architecture, stack and lifecycle make it a far easier thing to live with over time.
If you're weighing it up for a specific project, get in touch or have a look at how we handle Umbraco development, support and consultancy. Happy to tell you if the answer is WordPress.