---
title: "nginx vs Caddy"
slug: "nginx-vs-caddy"
category: "comparisons"
tags: ["comparisons", "nginx", "caddy", "web-server", "tls", "ops"]
status: "stable"
last_updated: 2026-05-14
summary: "Pick Caddy for automatic TLS and minimal config; pick nginx for fine-grained control, a mature module ecosystem, or deep operational familiarity."
related: ["[[ops/cloudflare]]", "[[ops/vercel]]", "[[cheatsheets/nginx-config]]", "[[comparisons/aws-vs-cloudflare]]", "[[ops/github-pages]]", "[[seo/technical]]", "[[comparisons/docker-vs-podman]]"]
---

## Overview

Pick Caddy for any new server where automatic TLS is the priority and the configuration fits a Caddyfile. Caddy provisions and renews certificates from Let's Encrypt and ZeroSSL with zero operator action; nginx requires Certbot, a cron job, and manual reload hooks. Pick nginx when the team has years of nginx configuration knowledge, the workload needs a specific module (ModSecurity, Lua, sticky sessions), or the deployment sits behind a CDN that terminates TLS anyway. The TLS automation gap is the main reason Caddy wins for solo operators and small teams. See [[cheatsheets/nginx-config]] for nginx pattern reference.

## When Caddy wins

Caddy is the right pick when operational simplicity and automatic TLS matter most.

- Automatic TLS: `Caddyfile` with a hostname triggers ACME certificate provisioning, renewal, and hot reload with no cron job or Certbot.
- Zero-downtime certificate rotation: Caddy reloads TLS configuration without dropping connections.
- HTTP/2 and HTTP/3 by default: no flag to set; Caddy enables QUIC transport automatically where supported.
- Caddyfile syntax is declarative and terse; a reverse proxy with TLS is three lines. An equivalent nginx config with Certbot integration is 30+ lines across multiple files.
- JSON config API: Caddy exposes a REST API for live configuration changes without reloads; useful for dynamic upstreams in containerized environments.
- Built-in basic auth, request rewriting, and header manipulation without third-party modules.
- Single binary with no runtime dependencies; easy to embed in containers.

## When nginx wins

nginx is the right pick when operational depth or module breadth is required.

- Module ecosystem: ModSecurity (WAF), OpenResty (Lua scripting), `ngx_http_auth_request_module`, sticky load balancing, and dozens of community modules exist only for nginx.
- Configuration granularity: nginx exposes every connection parameter (keepalive timeouts, upstream health check intervals, buffer sizes, proxy buffering) with documented semantics. Caddy's documentation for equivalent tuning is thinner.
- Operational familiarity: most infrastructure engineers know nginx. Hiring, runbooks, and Stack Overflow coverage favor nginx overwhelmingly.
- Kubernetes Ingress: the `ingress-nginx` controller is the default in most cluster setups; Caddy's ingress support is less mature.
- Static file serving at very high concurrency: nginx's event model and sendfile support are highly tuned; at 100k+ concurrent connections, nginx has more published tuning art.
- When TLS terminates at a CDN (Cloudflare, Fastly): the automatic TLS advantage disappears and nginx's control advantage remains. See [[comparisons/aws-vs-cloudflare]].

## Trade-offs at a glance

| Dimension              | Caddy                                  | nginx                                    |
| ---------------------- | -------------------------------------- | ---------------------------------------- |
| Automatic TLS          | Built-in ACME                          | Certbot + cron required                  |
| HTTP/3 (QUIC)          | Default                                | Module; nginx Plus or recompile          |
| Config syntax          | Caddyfile (terse) or JSON API          | Declarative blocks; verbose              |
| Live config reload     | JSON API; no process restart           | `nginx -s reload`; brief connection drop |
| Module ecosystem       | Limited; Go plugins                    | C modules; very broad                    |
| WAF                    | No native WAF                          | ModSecurity                              |
| Kubernetes Ingress     | Limited controller support             | `ingress-nginx` is the default           |
| Static file perf       | Good                                   | Best-in-class at high concurrency        |
| Container footprint    | Single binary                          | Multi-package with dynamic modules       |
| Documentation depth    | Improving; still gaps                  | Extensive; 15+ years of guides           |
| License                | Apache 2.0                             | BSD (open source) / nginx Plus (paid)    |

## Migration cost

nginx-to-Caddy is feasible for most simple proxy configs; Caddy-to-nginx is straightforward given nginx's flexibility.

- nginx to Caddy: map `server` blocks to Caddyfile site blocks. Rewrite `location` directives as Caddy `handle` or `route` blocks. Lua scripts and ModSecurity rules require alternative approaches (move WAF logic to Cloudflare, rewrite Lua as a sidecar service). Plan one engineer-day per site for simple proxies; one week for complex multi-upstream configs.
- Caddy to nginx: generate or write `server` blocks for each Caddyfile site. Add Certbot for TLS. The reverse is rarely blocked on feature gaps. Plan half a day per site.
- When migrating between servers, verify [[seo/technical]] signals (canonical URLs, redirects, HSTS headers) are replicated exactly before switching DNS.

## Recommendation

- New VPS or bare-metal server for a small product: Caddy. Automatic TLS alone is worth the switch.
- Kubernetes cluster with standard ingress: nginx via `ingress-nginx`. Caddy's ingress is not production-ready for most setups.
- WAF requirement on the origin: nginx with ModSecurity, or offload WAF to Cloudflare (see [[ops/cloudflare]]).
- CDN-fronted deployment where Cloudflare terminates TLS: either works; lean toward nginx for ecosystem reasons.
- Team with zero existing nginx knowledge: Caddy; the learning curve is lower.
- High-traffic static asset delivery: nginx with `sendfile on` and tuned worker connections.

## Related

- [[ops/cloudflare]]
- [[ops/vercel]]
- [[cheatsheets/nginx-config]]
- [[comparisons/aws-vs-cloudflare]]
- [[ops/github-pages]]
- [[seo/technical]]
- [[comparisons/docker-vs-podman]]
