How to Implement Traffic Mirroring in Nginx for Server Replication


3 views

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;
    }
}