How to Build a High‑Performance API Gateway with OpenResty and Lua
This article explains the role of API gateways, compares access‑layer and application‑layer designs, and provides a step‑by‑step guide to constructing a dynamic, high‑throughput gateway using OpenResty’s Nginx‑Lua architecture, plugin system, and runtime configuration features.
Preface
After sharing several gateway‑related posts, we noticed strong interest, so this article introduces how to use OpenResty to build a gateway system, summarizing key OpenResty concepts and providing a comprehensive overview of its high‑performance web platform.
Gateway Role
A gateway is the entry point for all requests, handling security, rate limiting, circuit breaking, monitoring, logging, risk control, and authentication. Two types exist:
Access‑layer gateway: routing, WAF, rate limiting, logging, caching, and forwarding requests to application‑layer gateways.
Application‑layer gateway: after routing, it performs authentication, timeout handling, retries, and circuit breaking for microservices written in various languages.
The access layer bears the entire traffic load, making its design critical for overall system capacity.
Access‑Layer Gateway Architecture and Implementation
The core function is routing requests to the appropriate backend cluster based on routing rules . Required capabilities include:
Routing: forward requests to upstream clusters according to host, URL, etc.
Plugin‑based routing strategy: authentication, rate limiting, security checks, etc., are implemented as independent, dynamically configurable plugins that can be added or removed without restarting.
Dynamic backend cluster changes: support adding or removing servers on the fly.
Monitoring and statistics: request volume, error rates, and logging for alerting and analysis.
Understanding OpenResty is essential to achieve these features.
Technical Selection
While Nginx offers high performance with an epoll model, it lacks runtime APIs for dynamic configuration, requiring configuration reloads. OpenResty extends Nginx with Lua, providing a programmable, dynamically configurable platform. Its key advantages are extensive documentation, test cases, and built‑in non‑blocking coroutine support.
OpenResty® is a high‑performance web platform based on Nginx and Lua, integrating many Lua libraries and third‑party modules to handle massive concurrency and provide dynamic web services.
OpenResty = Nginx + Lua, allowing runtime control of routing, upstreams, SSL, requests, and responses without restarting.
OpenResty Principle Analysis
Working Principle
OpenResty inherits Nginx’s architecture: a master process manages worker processes, which handle client requests using an asynchronous, non‑blocking event‑driven model (epoll). Each worker runs a single‑threaded Lua VM, and Lua coroutines cooperate with Nginx’s event loop to achieve massive concurrency.
When a Lua script performs I/O (e.g., MySQL or Redis queries), it yields, registers a callback with Nginx, and the worker can process other requests. Once the I/O completes, Nginx resumes the coroutine, ensuring non‑blocking behavior.
<code>local res, err = query_mysql(sql)
local value, err = query_redis(key)</code>The
syncvs
asyncand
blockingvs
non‑blockingconcepts are explained in the article.
OpenResty Request Lifecycle
Nginx processes each request through 11 phases; OpenResty provides corresponding
*_by_luadirectives such as
set_by_lua,
rewrite_by_lua,
access_by_lua,
content_by_lua,
header_filter_by_lua,
body_filter_by_lua, and
log_by_lua. This modularity enables separating concerns—for example, decrypting requests in the access phase and encrypting responses in the body‑filter phase without touching core business logic.
<code># Plain protocol version
location /request {
content_by_lua '...'; # handle request
}
# Encrypted protocol version
location /request {
access_by_lua '...'; # decrypt request
content_by_lua '...'; # process request
body_filter_by_lua '...'; # encrypt response
}</code>Worker‑Shared Data: shared_dict
OpenResty provides shared_dict , an efficient in‑memory key‑value store with atomic Lua APIs, allowing data sharing across independent worker processes.
Routing Strategy Pluginization
Routing policies are defined as
{url, action, cluster}entries stored in a database. At startup, workers fetch these rules, compile them into Lua functions, and cache them in
shared_dict. When rules change, the control plane notifies OpenResty to reload them.
Dynamic Backend Cluster Configuration
Static
upstreamblocks require manual edits and reloads. OpenResty’s
dyupsmodule offers an API to add, delete, or modify upstreams at runtime, eliminating reload overhead.
<code># Dynamic upstream API
server {
listen 127.0.0.1:81;
location / { dyups_interface; }
}
# Add upstream
curl -d "server 10.53.10.191;" 127.0.0.1:81/upstream/user_backend
# Delete upstream
curl -i -X DELETE 127.0.0.1:81/upstream/user_backend</code>Final Architecture Diagram
The design achieves a configurable, dynamic gateway capable of handling massive traffic with low latency.
Conclusion
Choosing OpenResty for a gateway offers high performance, proven adoption by major companies, and a rich ecosystem for dynamic routing, pluginization, and runtime configuration. While the article covers core concepts, OpenResty provides many more features for deeper exploration.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.