Caddy vs. Traefik: Which Reverse Proxy Fits Your Setup?
Caddy and Traefik compared head to head: configuration, Docker integration, certificates, middlewares and Kubernetes – with a clear verdict on when to pick which.
Two hands-on guides appeared here recently: Traefik as a reverse proxy with four services behind one domain and Caddy with automatic HTTPS as the lean alternative. Both tools solve the same core problem – several services behind one domain, certificates handled automatically. Which leaves the question that actually matters in practice: which one should you pick? This post puts them side by side.
What both do equally well
The similarities first, because they are bigger than the marketing pages suggest. Both are written in Go and ship as a single binary or a slim container image. Both obtain certificates from Let's Encrypt via ACME on their own, renew them in time and redirect HTTP to HTTPS. Both speak HTTP/3: Caddy enables it by default, Traefik needs a single http3 option on the entrypoint. Both are open source and at home in the Docker world. In other words: for "get two or three containers online securely", either is the right answer – you won't go wrong with one or the other.
The core difference: where does configuration come from?
The real difference is not a feature list but a philosophy.
Caddy thinks in a file. The Caddyfile describes the desired state: one block per service, usually a single reverse_proxy line. When a service is added, you edit the file and apply it with a zero-downtime caddy reload. That is deliberately simple – and exactly right for a handful of stable services.
Traefik thinks in events. It watches a provider – with the Docker provider, the Docker socket – and builds its routes dynamically from labels. When a container with matching labels starts, the route exists; when it stops, the route disappears. The routing rule lives right next to the service in your compose file, not in a central proxy configuration. With many or frequently changing containers, this is where Traefik shines.
To be fair: Caddy can be switched to label-based operation via a community plugin (caddy-docker-proxy) – but that is an add-on, not a built-in.
Head to head
| Caddy | Traefik | |
|---|---|---|
| Configuration | Caddyfile (central file, caddy reload) |
dynamic from providers (Docker labels etc.), no reload |
| Docker integration | file + reload; labels only via community plugin | native Docker provider, routes follow containers |
| Certificates | Let's Encrypt and ZeroSSL with automatic failover | Let's Encrypt via TLS, HTTP or DNS challenge |
| Wildcard certificates | DNS challenge, provider as module (caddy-dns) | DNS challenge, many providers built in |
| On-demand TLS (customer domains) | ✔ built in – certificate at first handshake | – |
| Static files / web server | ✔ full web server (file_server) |
– (proxy only) |
| Ready-made middlewares | basics on board, much via modules | extensive: BasicAuth, RateLimit, Retry, circuit breaker, ForwardAuth, IPAllowList … |
| Dashboard | – (admin API) | ✔ built-in dashboard |
| Kubernetes | no established ingress controller | ✔ established: Ingress, CRD, Gateway API |
| Local testing | built-in local CA (tls internal, .localhost) |
Let's Encrypt staging |
| Learning curve | very flat | flat to start, more concepts (static/dynamic, routers, middlewares) |
What only Caddy can do
Two things stand out. First, Caddy is a full web server: serving a static site while proxying two containers next to it is one instance and three lines of Caddyfile. Traefik cannot do that – it only proxies. Second, on-demand TLS: Caddy can obtain a certificate at the moment of the first TLS handshake, without the domain being configured beforehand. If your customers point their own domains at your application (white-label/SaaS), this is a unique capability that otherwise requires elaborate custom tooling. Add the built-in local CA: HTTPS testing without internet access and without Let's Encrypt, using tls internal or a .localhost address.
What only Traefik can do
Traefik is the better platform. Its toolbox of routers and ready-made middlewares (rate limiting, basic auth, retry, circuit breaker, ForwardAuth for SSO gateways) covers – without extra modules – what growing setups eventually need. The built-in dashboard shows at any time which routes were created from which labels – worth gold when debugging. And if Kubernetes is on your path, Traefik is an established ingress controller including Gateway API support; a comparably widespread Caddy ingress does not exist. Beyond Docker and Kubernetes, Traefik also reads configuration from Nomad, Consul, ECS or key-value stores.
Verdict: which tool for which job?
Pick Caddy if …
- you publish a handful of stable services and want the simplest working solution,
- static content and proxying should come from one tool (web server included),
- customers connect their own domains (on-demand TLS),
- you test a lot locally or internally with HTTPS (built-in CA).
Pick Traefik if …
- containers come, go and move frequently – routes should follow services automatically,
- you need middlewares like rate limiting, ForwardAuth or circuit breakers without tinkering,
- a dashboard for runtime diagnostics matters to you,
- Kubernetes is on the roadmap – then there is hardly a way around Traefik.
As a rule of thumb: Caddy is the fastest path to "runs securely", Traefik scales best with you. You can try both in under 15 minutes – the working minimal stacks are in the two guides on Traefik and Caddy. For the details, the primary sources are the Caddy documentation and the Traefik documentation.
Note: The articles on this blog are produced with the help of AI and are editorially reviewed before publication. Editorial responsibility lies with Emre Yurtbay (see the Impressum).