Nginx's mirror module allows you to duplicate incoming requests and send them to additional backend servers without affecting the primary request flow. This is particularly useful for:
- Testing new server configurations with real production traffic
- Performance benchmarking
- Data analysis pipelines
- Blue-green deployment validation
Here's a fundamental configuration to mirror traffic from Server N to both Servers A and B:
http {
upstream primary_backend {
server A.example.com;
}
upstream mirror_backend {
server B.example.com;
}
server {
listen 80;
location /resource {
mirror /mirror;
mirror_request_body on;
proxy_pass http://primary_backend;
}
location = /mirror {
internal;
proxy_pass http://mirror_backend$request_uri;
proxy_pass_request_body on;
proxy_set_header X-Original-URI $request_uri;
}
}
}
For more advanced cases where you need conditional mirroring or different mirroring rates:
map $http_user_agent $mirror_ua {
default 0;
"~*bot" 0;
"~*Mozilla" 1;
}
server {
# ... other config ...
location / {
if ($mirror_ua) {
mirror /mirror;
mirror_request_body on;
mirror_rate 0.5;
}
proxy_pass http://primary_backend;
}
}
When implementing traffic mirroring, keep these factors in mind:
- Mirroring doubles the outgoing bandwidth from your Nginx instance
- Mirrored requests don't wait for responses from the mirrored backend
- Enable
mirror_request_body
only when necessary to reduce overhead - Consider using
mirror_rate
to limit mirroring volume
Some problems you might encounter:
# Check for mirror module in your Nginx build
nginx -V 2>&1 | grep -o with-http_mirror_module
# Common errors:
# - "mirror" directive is unknown (module not compiled)
# - 502 errors on mirrored backend (check connectivity)
# - Missing request bodies (enable mirror_request_body)
In modern web architectures, there are cases where you need to duplicate incoming requests to multiple backend servers simultaneously. Common use cases include:
- Testing new server deployments without affecting production traffic
- Data migration between different server environments
- Load testing with real production traffic patterns
- Implementing blue-green deployment strategies
Nginx provides the ngx_http_mirror_module
(available since version 1.13.4) specifically for this purpose. Unlike simple proxying, mirroring sends requests to additional backend servers without waiting for responses, making it ideal for non-blocking traffic duplication.
server {
listen 80;
server_name example.com;
location /resource {
mirror /mirror; # Primary mirror directive
proxy_pass http://server-a;
# Optional timeout settings
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
location = /mirror {
internal; # Makes this location inaccessible from outside
proxy_pass http://server-b$request_uri;
# These headers help track mirrored requests
proxy_set_header X-Mirrored "true";
proxy_set_header X-Original-Host $host;
}
}
For more complex scenarios, consider these enhancements:
# Mirroring with conditional logic
map $http_user_agent $is_mirrorable {
default 1;
"~*bot|crawler" 0; # Don't mirror bot traffic
}
server {
location /api {
mirror /mirror if=$is_mirrorable;
proxy_pass http://primary-backend;
}
}
# Multiple mirror destinations
location /critical {
mirror /mirror1;
mirror /mirror2;
proxy_pass http://main-server;
}
location = /mirror1 {
internal;
proxy_pass http://backup-server-1$request_uri;
}
location = /mirror2 {
internal;
proxy_pass http://backup-server-2$request_uri;
}
When implementing traffic mirroring:
- Subrequests created by mirroring consume additional resources
- Consider rate limiting for mirror destinations to prevent overload
- Mirrored requests don't affect the original request's response time
- Monitor memory usage as each mirrored request creates a copy
The mirror module has some important behavioral characteristics:
- Mirrored requests proceed independently of the main request
- Failures in mirrored requests don't affect the original response
- You can log mirror request outcomes separately:
log_format mirror_log '$remote_addr - $status - $request_time';
location = /mirror {
internal;
proxy_pass http://mirror-backend$request_uri;
access_log /var/log/nginx/mirror_access.log mirror_log;
}
For cases where you need conditional routing rather than pure mirroring:
split_clients $request_id $mirror_backend {
50% "";
50% "http://mirror-server";
}
server {
location / {
proxy_pass $mirror_backend;
proxy_pass http://primary-server;
}
}