There's a particular kind of technology decision that never gets made consciously. You don't sit down one afternoon and decide to change your default web server. You just look up one day and realise that the thing you now reach for first isn't the thing you reached for first ten years ago — and you're not entirely sure when that happened.
That's the honest story of Nginx and Apache for me. So rather than write another "which is faster" comparison — the internet has enough of those, and most of them are arguing about benchmarks that stopped mattering years ago — I want to walk through how my own default actually shifted, and what that says about which server belongs where.
The Apache years, which were most of them
I ran Apache for the better part of two decades, and the reason is almost embarrassingly simple: it was the standard. When you learned to run web servers, you learned Apache. When you rented a server or set one up, Apache was what went on it. The documentation assumed it, the tutorials assumed it, the hosting control panels assumed it. It was the default in the truest sense — the thing you'd use unless you had a specific reason not to.
And it earned that position. Apache is enormously capable, endlessly configurable, and it has a module for very nearly everything. Its per-directory configuration model — the much-maligned .htaccess file — is genuinely powerful in the right context. It let you drop a small config file into a folder and change behaviour for just that folder, without touching the main server config or restarting anything. On shared hosting, where one server hosts dozens of customers who each need to tweak their own corner without being handed the keys to the whole machine, that model isn't just convenient. It's the entire reason the arrangement works.
For years, I had no reason to look past it. The sites I ran, Apache ran well. If something needed doing, Apache had a module or a directive for it. Familiarity is a real advantage in infrastructure — the tool you know deeply is often the right tool simply because you'll configure it correctly and troubleshoot it quickly. I knew Apache deeply.
The reverse-proxy door
I didn't come to Nginx because I went looking for a better web server. I came to it because I needed a reverse proxy, and Nginx was the tool everyone pointed at for the job.
If you haven't hit this need yet: a reverse proxy sits in front of one or more backend services and routes incoming requests to the right place. Someone visits one of several sites, or one of several applications, all arriving on the same public address, and the proxy works out where each request should actually go — then passes the response back as if it had served it itself. It's the traffic director standing at the front door.
Nginx is very, very good at this. It was designed from the ground up around exactly this kind of work — handling many simultaneous connections, passing them efficiently to backends, serving what it can directly and forwarding the rest. The first time I set one up, the thing that struck me wasn't performance. It was how naturally the configuration expressed what I was actually trying to do. Here's the front door, here are the services behind it, here's which requests go where.
I didn't switch defaults on principle. I walked through the reverse-proxy door for one job, found the room comfortable, and kept coming back.
Once Nginx was in my toolkit for reverse proxying, it started turning up in other places. A small static site that just needed serving quickly and cheaply. A single-purpose service that didn't need Apache's full weight behind it. Each time, Nginx fit — not dramatically better, just cleanly, with a smaller footprint and less that I needed to configure to get where I was going.
The architectural difference, in plain English
Underneath the preference is a real design difference, and it's worth understanding because it explains why each server feels the way it does — without needing to wade into benchmark wars.
Classic Apache handles requests using processes or threads: broadly, each connection gets its own worker to look after it. This model is straightforward, robust, and flexible — that per-worker isolation is part of what makes Apache's module system and per-directory configuration so powerful. But it has a cost. Each worker consumes memory, and when you have a great many connections open at once — many of them slow, idle, or just holding the line — you end up with a great many workers sitting around consuming resources.
Nginx took a different approach. Instead of a worker per connection, it uses a small number of worker processes, each of which juggles a large number of connections at once using an event-driven model — reacting to activity as it happens rather than dedicating a worker to each conversation. The practical upshot is that Nginx tends to hold a lot of concurrent connections using very little memory. That's the "smaller footprint" I kept running into. It wasn't magic; it was architecture.
Worth being honest about: the old "Nginx is faster than Apache" line is largely a relic. Modern Apache has event-driven processing available too, and for most real-world sites the web server is nowhere near the bottleneck — your database, your application code, and your network will hit their limits long before the choice of web server does. Where the architectural difference genuinely shows is high-concurrency connection handling and resource footprint, not raw page-serving speed for a typical site.
Where Apache still earns its place
None of this is a eulogy for Apache. I'm a "best tool for the job" person, and there are still jobs Apache is better suited to. Reaching for Nginx reflexively everywhere would be exactly the same mistake as reaching for Apache reflexively everywhere — just with a different logo.
Apache still shines when you need per-directory configuration you don't fully control centrally. The .htaccess model — letting a config file in a folder override behaviour for that folder — is a genuine feature, not a bug, when you're running shared hosting or handing parts of a site to people who need to adjust their own rules without server-level access. Nginx deliberately doesn't do this; it wants its configuration central and loaded once, which is faster and cleaner but assumes you hold all the keys.
Apache also still wins on drop-in flexibility and module depth. Its ecosystem is vast and mature, and a lot of software, documentation, and hosting environments still assume it. If you're deploying something that expects Apache, that ships with Apache configuration, or that leans on a specific Apache module, the path of least resistance — and often the correct engineering choice — is to just use Apache. Familiarity counts here too: a shop that knows Apache deeply will run it more safely than they'd run a hastily-adopted Nginx.
Where Nginx wins for the work I do now
What changed for me wasn't really a discovery that one server is better. What changed was the nature of the work.
More and more of what I do now involves smaller, single-purpose services rather than big monolithic sites. More of it is automated — spun up, configured, and torn down by scripts and pipelines rather than hand-tended. More of it runs in containers, where a small footprint and a fast, predictable startup genuinely matter. And nearly all of it sits behind a reverse proxy that routes traffic to the right service.
Every one of those shifts happens to favour Nginx. The small footprint suits containers and lightweight services. The event-driven model suits high connection counts. The central, declarative configuration suits automation — it's far easier to template and generate an Nginx config from a script than to orchestrate a pile of Apache directives and .htaccess files. And the reverse-proxy role, the thing that got me in the door in the first place, is now central to how almost everything is wired together.
My default didn't shift because Nginx won an argument. It shifted because the work changed, and the new work happens to fit the way Nginx is built.
From hand-coded vhosts to the reverse proxy
There's one more piece to this, and it's the part I find genuinely striking when I stop and look at it.
There was a time — and I lived plenty of it — when running many sites on a single server meant hand-coding Apache virtual host configurations, one after another. Each site its own block, each with its own document root, its own logging, its own SSL setup, all of it juggled by hand in the server config and kept straight through sheer discipline. Add a site, edit the config, test it, reload, hope you didn't fat-finger a directive that took the other twenty sites down with it. It worked, but it was fiddly, error-prone, and it did not scale gracefully.
The reverse proxy quietly dissolved most of that problem. Now the pattern is different: each site or service is its own small, self-contained thing, and a reverse proxy out front handles the routing, the SSL, and the traffic direction for all of them from one coherent place. Adding a site isn't a nervous edit to a monolithic config that could break everything — it's a new, isolated entry that doesn't touch the others. Tools built around this model make standing up a new site behind the proxy close to trivial compared to the vhost-juggling days.
That's a long way from where I started. And it's why, when people ask which is better, I don't think it's quite the right question. The honest answer is that the ground moved. The work became more automated, more containerised, more service-oriented — and the tooling that fits that world well is, more often than not, Nginx.
So which should you use?
Genuinely: it depends, and less dramatically than the framing suggests. For a typical site, either will serve you well and the web server won't be your bottleneck. If you're on shared hosting or need per-directory overrides you don't centrally control, Apache's model is a real advantage. If you're deploying something that expects Apache, use Apache. If you know Apache deeply and don't know Nginx, that knowledge is worth more than a marginal architectural edge.
But if you're doing what a lot of us are doing now — running smaller services, automating deployments, working in containers, and routing everything through a reverse proxy — you'll probably find, as I did, that Nginx quietly becomes the thing you reach for first. Not because someone won a benchmark. Because the job changed shape, and it fits.
Best tool for the job. It's just that the jobs I'm doing these days tend to have Nginx-shaped holes in them.
Need a hand deciding what fits your setup? Web server choice, reverse proxies, and hosting architecture are part of what I do day to day. If you'd like a straight answer for your specific situation, get in touch.
Get in touch →