Backend Development 9 min read

Leveraging ngx_lua for Traffic Grouping in Nginx

This article explains how to use the ngx_lua module in Nginx to assign traffic tags, implement header‑based or domain‑based routing, and integrate with dynamic upstreams for parallel testing, load testing, and gray‑release scenarios, providing code examples and configuration details.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
Leveraging ngx_lua for Traffic Grouping in Nginx

Background

In a testing environment multiple features need to be tested in parallel, requiring Nginx to forward traffic to specific test machines based on certain information. Full‑link load testing without traffic separation impacts online users and must be performed during low‑traffic periods, which is costly and requires manual supervision. Gray‑release also needs Nginx to direct traffic to designated gray‑release servers.

ngx_lua Module

ngx_lua embeds the Lua language into Nginx, allowing developers to write Lua scripts that run inside Nginx, turning it into a high‑performance web container. The module provides many APIs for interacting with Nginx, and developers only need to learn these APIs to implement functionality.

ngx_lua Execution Phases

The module’s directives are executed within Nginx’s 11 processing phases, but not all phases run Lua code. Directives can be placed in http, server, server if, location, and location if contexts.

Directive

Phase

Scope

Description

init_by_lua

init_by_lua_file

loading‑config

http

Executed when the master process loads the configuration; typically used for global initialization or pre‑loading Lua modules.

init_worker_by_lua

init_worker_by_lua_file

starting‑worker

http

Runs when each worker process starts; often used for periodic configuration fetching, health checks, etc.

set_by_lua

set_by_lua_file

rewrite

server, server if, location, location if

Sets Nginx variables with complex logic; this is a blocking operation, so Lua code must be fast.

rewrite_by_lua

rewrite_by_lua_file

rewrite tail

http, server, location, location if

Handles rewrite phase, enabling complex forwarding or redirection logic.

access_by_lua

access_by_lua_file

access tail

http, server, location, location if

Runs during request access phase for access control.

content_by_lua

content_by_lua_file

content

location, location if

Content handler that processes the request and generates a response.

header_filter_by_lua

header_filter_by_lua_file

output‑header‑filter

http, server, location, location if

Sets response headers and cookies.

body_filter_by_lua

body_filter_by_lua_file

output‑body‑filter

http, server, location, location if

Filters response body, e.g., truncation or replacement.

log_by_lua

log_by_lua_file

log

http, server, location, location if

Log phase processing, such as recording request counts or average response time.

Setting Traffic Tags

Method 1: The client adds a tag to the request header and accesses the original domain.

if (tag == "" or checkTag(host_pass, tag) == false) then
    return host_pass;
end
...
return host_pass .. "_" .. tag;
set_by_lua_file $host_pass set_tag.lua;

Method 2: The client appends the tag to the domain name; Nginx extracts the tag from the host, adds it to the header, and forwards the request.

local host = ngx.var.host
local hostList = split(host, ".")
local subDomain = split(hostList[1], "-")
...
ngx.req.set_header("global-route-tag", subDomain[2])
ngx.header["global-route-tag"] = subDomain[2]
...
local test_host = ipList[1] .. "." .. hostList[2] .. "." .. hostList[3]
return test_host
set_by_lua_file $test_host set_test_servers.lua ;

location / {
    ...
    proxy_pass http://$host_pass;
    proxy_set_header Host $test_host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Method 1 requires external tools to add tags to headers, which is less intuitive for API testing. Method 2 reduces operational complexity and avoids host‑binding issues on corporate networks, so it is recommended for internal testing.

Integration with dyups Tagged Services

In a previous article we described smooth service rollout using Nginx. The current implementation extends the incremental update queue to support services with tags; tags are concatenated into the upstream name, enabling seamless rollout with traffic grouping.

Reference: "How ZheZhe WEB Service Achieves Smoother Changes"

Result

By publishing with tag‑based groups, the same service can be deployed to different groups, each carrying a distinct tag. This adds online traffic segmentation, solving problems for load testing, gray releases, and other scenarios.

Conclusion

Combining Nginx with Lua provides a versatile Swiss‑army‑knife‑like platform that easily solves many problems. Common practice patterns include Web Application Firewall (WAF), rate limiting, degradation, and service quality monitoring.

About the Author

Zhao Yunzhou, ZheZhe Operations Development, responsible for automation tools and platform support. Passionate about thinking and operations.

Backendload balancingtraffic routingnginxLua scriptingngx_lua
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.