
August 22, 2026
10 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
Running multiple backend services behind a single entry point is standard practice, but configuring the routing layer often becomes a bottleneck. Using Traefik as an API Gateway solves this by automatically discovering containers and applying middleware without manual config reloads. If you are building Laravel APIs or microservices in Docker, Traefik eliminates the friction of maintaining static Nginx configs while providing native support for modern cloud-native patterns.
How does Traefik as an API Gateway differ from Nginx?
The fundamental difference lies in configuration philosophy. Nginx is a static reverse proxy that requires explicit configuration files and reload signals when upstreams change. Traefik is a dynamic edge router designed for ephemeral infrastructure. When I deploy Laravel applications using Deployer and GitLab CI on shared EC2 instances, the ability to spin up a new container and have it immediately routable—without touching a central config file—is a massive operational advantage.
In practice, this means your routing logic lives next to your application code in docker-compose.yml rather than in a separate infrastructure repository. For agencies managing multiple client sites like legal-tech portals or eCommerce platforms on shared infrastructure, this reduces the cognitive load significantly. You don't need to remember which port maps to which domain; the label defines it.
| Feature | Nginx (Traditional) | Traefik as an API Gateway |
|---|---|---|
| Configuration | Static files (nginx.conf) | Dynamic labels + optional file providers |
| Service Discovery | Manual upstream definition | Automatic via Docker/K8s/Consul API |
| SSL/TLS Management | Certbot + cron + reload | Native Let's Encrypt with auto-renewal |
| Middleware Chain | Lua/OpenResty or external modules | Built-in plugins (Auth, RateLimit, Headers) |
| Reload Behavior | Requires nginx -s reload | Hot-reload without dropping connections |
| Observability | Access logs only (unless enhanced) | Real-time dashboard + metrics export |
How do you configure Traefik for Laravel Docker containers?
Setting up Traefik for a Laravel application running in PHP-FPM 8.4 requires exposing the correct internal port and defining host-based routing. On production systems I maintain, I typically run Traefik v3.x alongside the application stack. The key is ensuring the Docker provider is enabled and the network is correctly shared.
Base Docker Compose Configuration
This configuration assumes you have a traefik-public network created externally. This separation prevents backend services from being accidentally exposed to the public internet without passing through the gateway.
<!-- docker-compose.yml -->
services:
traefik:
image: traefik:v3.1
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.le.acme.email=admin@example.com"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- traefik-public
laravel-app:
image: my-laravel-app:php8.4-fpm
labels:
- "traefik.enable=true"
- "traefik.http.routers.laravel.rule=Host(`api.example.com`)"
- "traefik.http.routers.laravel.entrypoints=websecure"
- "traefik.http.routers.laravel.tls.certresolver=le"
- "traefik.http.services.laravel.loadbalancer.server.port=8080"
- "traefik.docker.network=traefik-public"
networks:
- traefik-public
- default
networks:
traefik-public:
external: true A common mistake here is forgetting traefik.docker.network. If your container is attached to multiple networks (which is typical for Laravel apps connecting to MySQL/Redis), Traefik might pick the wrong IP address, resulting in 502 Bad Gateway errors. Explicitly naming the network ensures traffic flows through the intended interface.
Handling Non-Standard Ports
Laravel Octane or FrankenPHP setups often listen on port 8000 or 8080 instead of the default 80. Always specify traefik.http.services.<name>.loadbalancer.server.port explicitly. Relying on auto-detection works for standard Nginx/Apache containers but frequently fails for custom PHP runtimes.
What middleware should every API gateway implement?
Routing is only half the job. A competent API gateway must enforce security and reliability policies at the edge. When architecting REST APIs in Laravel, I offload cross-cutting concerns to Traefik so the application code remains focused on business logic.
Rate Limiting at the Edge
Protecting your Laravel API from abuse shouldn't wait until the request hits PHP. Define a global rate limit middleware to absorb spikes before they consume expensive application resources.
labels:
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=50"
- "traefik.http.middlewares.api-ratelimit.ratelimit.period=1m"
- "traefik.http.routers.laravel.middlewares=api-ratelimit@docker" This configuration allows 100 requests per minute on average with bursts up to 50. For multi-tenant SaaS platforms where different clients have different quotas, consider using the rateLimit.sourceCriterion.ipStrategy or custom headers to differentiate users before they reach your application's throttle middleware.
Authentication Offloading
For internal dashboards or staging environments, Basic Auth at the gateway level prevents unauthorized access entirely. For production APIs requiring JWT validation, Traefik's ForwardAuth middleware delegates verification to a lightweight auth service, keeping your main Laravel app free from repetitive token parsing on health checks or public endpoints.
- "traefik.http.middlewares.internal-auth.basicauth.users=admin:$$apr1$$xyz..."
- "traefik.http.routers.dashboard.middlewares=internal-auth@docker" Note the double dollar signs ($$) in Docker Compose files. This escapes the variable interpolation syntax. Missing this escaping is one of the most frequent issues I see when developers first adopt Traefik for securing admin panels.
How do you handle SSL and canonical redirects in production?
Every production API must enforce HTTPS and normalize URLs. Traefik handles this natively through entrypoint redirections and certificate resolvers, eliminating the need for separate Certbot containers or cron jobs.
Global HTTP to HTTPS Redirect
Configure this once at the entrypoint level rather than per-router. This ensures every service inherits secure-by-default behavior.
command:
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entryPoint.permanent=true" Canonical Domain Enforcement
SEO and cookie consistency require enforcing a single canonical domain. If your legal-tech portal serves both www.notarynepal.com and notarynepal.com, redirect one to the other at the gateway. This prevents duplicate content issues and ensures session cookies work reliably across all entry points.
labels:
- "traefik.http.routers.www-redirect.rule=Host(`www.notarynepal.com`)"
- "traefik.http.routers.www-redirect.middlewares=strip-www"
- "traefik.http.middlewares.strip-www.redirectregex.regex=^https://www\\.(.+)"
- "traefik.http.middlewares.strip-www.redirectregex.replacement=https://$1"
- "traefik.http.middlewares.strip-www.redirectregex.permanent=true" When working on technical SEO audits for Nepali businesses, I frequently find missing canonical redirects causing indexation bloat. Fixing this at the Traefik level is far more reliable than relying on framework-level redirects, which may not trigger if caching layers intercept the request first.
When should you choose Traefik over other gateway solutions?
Traefik isn't universally superior—it's specifically optimized for dynamic, containerized environments. Understanding its boundaries prevents architectural mismatches.
Choose Traefik when:
- You run Docker Compose, Swarm, or Kubernetes with frequently changing services
- You want automatic Let's Encrypt management without external tooling
- Your team prefers declarative configuration co-located with application code
- You need built-in observability dashboards without additional monitoring stacks
Stick with Nginx/Caddy when:
- You manage static VPS deployments with infrequent changes
- You require advanced caching or complex rewrite rules better served by mature modules
- Your team has deep existing Nginx expertise and minimal containerization
- Performance benchmarks show measurable differences at your specific scale (rare below 10k RPS)
For most Laravel shops and agencies I work with in Nepal and globally, the operational savings from auto-discovery outweigh the marginal performance benefits of static proxies. The time saved debugging routing issues during deployments pays for itself within weeks.
Practical Production Considerations for Traefik
Beyond basic setup, several nuances determine whether Traefik succeeds in production. These lessons come from maintaining live systems handling real transactions, not toy examples.
Persistent Storage for Certificates
Always mount /letsencrypt/acme.json to persistent storage. Losing this file means re-issuing certificates on every restart, which quickly triggers Let's Encrypt rate limits. On EC2 instances, use EBS volumes or bind mounts to named Docker volumes—never ephemeral container storage.
Dashboard Security
The Traefik dashboard exposes sensitive routing information. Never expose it publicly without authentication. Either restrict access by IP using middleware or place it behind a VPN. In my deployments, the dashboard is typically accessible only via SSH tunnel or internal network, never on a public subdomain.
Log Aggregation Integration
Traefik outputs structured JSON access logs when configured properly. Forward these to your logging stack (Loki, ELK, or CloudWatch) for centralized analysis. Correlating gateway logs with Laravel application logs is essential for debugging latency issues that span the entire request lifecycle.
command:
- "--accesslog=true"
- "--accesslog.format=json"
- "--accesslog.fields.headers.names.X-Request-ID=keep"
- "--log.level=WARN" Health Checks for Resilience
Define health checks so Traefik stops routing to failing containers automatically. This is critical for zero-downtime deployments where old and new containers coexist briefly during transitions.
labels:
- "traefik.http.services.laravel.loadbalancer.healthcheck.path=/up"
- "traefik.http.services.laravel.loadbalancer.healthcheck.interval=10s"
- "traefik.http.services.laravel.loadbalancer.healthcheck.timeout=3s" Laravel's built-in /up endpoint (available since Laravel 11) works perfectly here. It returns 200 only when the application is fully booted and maintenance mode is disabled, preventing traffic from hitting partially initialized containers.
Moving Forward with Traefik as an API Gateway
Adopting Traefik as an API Gateway shifts routing complexity from static configuration files to dynamic, code-proximate declarations. For teams shipping Laravel APIs, microservices, or containerized eCommerce platforms, this alignment between application and infrastructure reduces deployment friction and operational overhead. Start with the base Docker Compose setup above, add middleware incrementally, and monitor the dashboard during initial rollout to verify routing behavior matches expectations.
If you're evaluating gateway options for a production system or need help migrating from static Nginx configs to a dynamic Traefik setup, reach out to discuss your architecture. I regularly help teams in Nepal and worldwide modernize their deployment pipelines while maintaining reliability and security standards.

