Open-source project
openresty/lua-nginx-module avatar
openresty/lua-nginx-module

lua-nginx-module puts LuaJIT coroutines inside Nginx's event model

Embed the Power of Lua into NGINX HTTP servers

11,794 stars2,053 forksCLicense varies

At a glance

What is it?
A C module that embeds LuaJIT into Nginx and hooks Lua coroutines onto Nginx subrequests, shipped separately from the Nginx source tree. You get non-blocking upstream calls when every network path stays on the Nginx API for Lua, and the project publishes a specific list of contexts where that promise breaks.
Who is it for?
Choose this module when you want to write upstream calls and caching logic in Lua inside Nginx and can keep every network path on the Nginx API for Lua, and treat it as the wrong choice when your traffic passes through SSI, SPDY, or a module that short-circuits requests.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • openresty/lua-nginx-module11,794 ★ · +12
Star history
Repository2026-09-222026-11-13
openresty/lua-nginx-module11.8k11.8k

12 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The module is not part of the Nginx source distribution

ngx_http_lua_module is not distributed with the Nginx source, and the project says so in its opening lines before pointing at its own installation section. Stock Nginx tarballs and distribution packages ship without it, and no stock compile switch turns it on. A config containing content_by_lua_block on a plain Nginx install fails at startup as an unknown directive, so the module has to be obtained and built on its own. Two routes are documented: building as a dynamic module, and a set of C macro configurations. The README's table of contents lists them as separate installation subsections. The checkout carries the pieces for either route: a config file for the nginx build, src/ for the C sources, doc/, t/ for the test suite, plus util/, misc/, dtrace/, tapset/ and valgrind.suppress. The synopsis itself is short, and it starts with the two search-path directives before any server block:

nginx

 # set search paths for pure Lua external libraries (';;' is the default path):
 lua_package_path '/foo/bar/?.lua;/blah/?.lua;;';

 # set search paths for Lua external libraries written in C (can also use ';;'):
 lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;';

 server {
     location /lua_content {
         # MIME type determined by default_type:
         default_type 'text/plain';

         content_by_lua_block {
             ngx.say('Hello,world!')
         }
     }

     location /nginx_var {
         # MIME type determined by default_type:
         default_type 'text/plain'

The synopsis shown ends partway through the second location, so it is not a complete config.

Only LuaJIT 2.0/2.1 runs, and PUC-Rio Lua was dropped at v0.10.16

The module embeds LuaJIT 2.0/2.1, and the documentation uses the words Lua and LuaJIT interchangeably to mean that one interpreter. Since version v0.10.16, the standard Lua interpreter, also called PUC-Rio Lua, is not supported anymore. That cutoff is the first thing to test against your own code. A library or application written for the standard interpreter can load here and still behave differently, and there is no second interpreter to fall back to, because the module ships one VM and it is the JIT one. The document in this repository describes v0.10.29, released on Oct 24, 2025, and lists Status as Production ready. The distinction between OpenResty and a self-built server also runs through this section: the module is a core component of OpenResty, so OpenResty users get it already assembled, while everyone else compiles it against their own Nginx and inherits the JIT-only constraint along with the build. If you are porting an existing Lua application, the v0.10.16 boundary is where time gets lost, because incompatibilities show up as wrong behaviour in your code rather than as a refused start.

One Lua state per worker process, shared by every request in it

The Lua interpreter, described as a Lua State or a LuaJIT VM instance, is shared across all requests in a single Nginx worker process, and request contexts are segregated so one request does not clobber another. That is the memory trade the module makes, and it is why the documentation gives Lua Variable Scope and Data Sharing within an Nginx Worker their own sections rather than treating globals as an afterthought. In practice the count of worker processes becomes the count of independent Lua states, so a global table, a module-level cache, or a pooled upstream connection lives inside one process and is invisible to its siblings. Worker count and worker restart behaviour are therefore part of your state design, not just a capacity setting. The corollary cuts the other way: a leaked global, a growing cache, or a dead pooled connection is shared by every other request running in that same worker, and requests can land on different workers and see different state.

Cosockets are not available in every context

The non-blocking claim is conditional, and the project states the condition: Lua code here can be 100% non-blocking on network traffic as long as the Nginx API for Lua is used to handle requests to upstream services such as MySQL, PostgreSQL, Memcached, Redis, or upstream HTTP web services. Step outside that API, call a blocking C library, or read a file synchronously, and the guarantee is gone. That is the axis on which the documentation contrasts this module with Apache's mod_lua and Lighttpd's mod_magnet. The Known Issues section then names where the mechanism breaks down: TCP socket connect operation issues, Lua Coroutine Yielding/Resuming, Lua Variable Scope, Locations Configured by Subrequest Directives of Other Modules, Cosockets Not Available Everywhere, Special Escaping Sequences, Mixing with SSI Not Supported, SPDY Mode Not Fully Supported, and Missing data on short circuited requests. For a reader, Cosockets Not Available Everywhere matters most, because cosockets are what the non-blocking story rests on. If the phase handling your request has no cosocket support, the non-blocking upstream call you planned is not available there, so check the Cosockets Not Available Everywhere section for which contexts are affected.

Subrequests reach other modules, but the resty libraries are the cheaper path

Almost any Nginx module can be used from Lua through ngx.location.capture or ngx.location.capture_multi. That is the escape hatch for upstreams with no Lua client: ngx_proxy, ngx_fastcgi, ngx_memc, ngx_redis, ngx_redis2 and ngx_postgres all become reachable from a location block, as does anything else compiled into the same server. The documentation still steers you away from it, recommending the lua-resty-* libraries instead of creating subrequests to access the Nginx upstream modules, and calling the former usually much more flexible and memory-efficient. The libraries named as usable here are lua-resty-memcached, lua-resty-mysql, lua-resty-redis, lua-resty-dns, lua-resty-upload, lua-resty-websocket, lua-resty-lock, lua-resty-lrucache, lua-resty-string, and lua-resty-logger-socket. The trade is explicit rather than hidden: capture needs no new dependency but costs more memory per the project's own wording, while each resty library adds a package you must vendor, pin and audit. A deployment that leans on capture purely to avoid a dependency ends up paying in worker memory.

SSI, SPDY and short-circuited requests are the documented no-go combinations

Three entries in the Known Issues list read as non-support rather than rough edges: Mixing with SSI Not Supported, SPDY Mode Not Fully Supported, and Missing data on short circuited requests. The first means a Lua handler and server-side includes cannot share a response path; the second means the project will not promise full behaviour under SPDY. The third, Missing data on short circuited requests, is the one to read first. The same list flags Locations Configured by Subrequest Directives of Other Modules. Separate documentation sections cover HTTP 1.0 support, LuaJIT bytecode support, System Environment Variable Support, and Statically Linking Pure Lua Modules, all worth reading before you commit a topology. The practical rule is to establish which module terminates or issues each request before assuming your Lua block owns the exchange end to end.

Versioning runs through tags, not GitHub releases

This repository has no GitHub releases, so the version signal is the tag and the Changes section rather than a feed you can subscribe to. The document here describes v0.10.29, released on Oct 24, 2025, and the last push landed on November 2, 2026, so patches are still arriving. The docs also keep a TODO section and an Obsolete Sections area holding Special PCRE Sequences and Lua/LuaJIT bytecode support, which means parts of the documentation tree still describe behaviour that no longer applies; lift configuration from that area and you may be reproducing an instruction the project already retired. Support runs through mailing lists, with separate English and Chinese lists, alongside Code Repository and Bugs and Patches sections that say where fixes land. The linked videos cover a Hello World HTTP example, writing your own Lua modules, the resty command-line utility demo, measuring execution time of Lua code correctly, and precompiling Lua modules into LuaJIT bytecode to speed up OpenResty startup. That last one is the item to watch if start-up time is on your critical path.

Editorial conclusion

Choose this module when you want to write upstream calls and caching logic in Lua inside Nginx and can keep every network path on the Nginx API for Lua, and treat it as the wrong choice when your traffic passes through SSI, SPDY, or a module that short-circuits requests. Before deploying, confirm the version your build actually embeds, since the document here covers v0.10.29 and the standard interpreter has been unsupported since v0.10.16, and read the cosocket and short-circuited-request notes in full, because both mark places where the non-blocking guarantee or the expected data does not hold.

Frequently asked questions

what is lua nginx module

It is ngx_http_lua_module, a C module that embeds LuaJIT 2.0/2.1 into Nginx and attaches Lua coroutines to the Nginx event model through subrequests. It is a core component of OpenResty, and it is not distributed with the Nginx source.

What is NGINX and why use it?

The documentation here answers a narrower version of that: inside Nginx, this module lets Lua coroutines run non-blocking on network traffic as long as requests to upstreams such as MySQL, PostgreSQL, Memcached, Redis or HTTP services go through the Nginx API for Lua.

Is Lua just C++?

No such comparison appears in the project. What it states is that the module embeds the LuaJIT 2.0/2.1 interpreter, that the repository code itself is C, and that the standard PUC-Rio interpreter has been unsupported since version v0.10.16.

Is Lua basically Python?

The project makes no such claim. Its only statement about the language itself is that it embeds LuaJIT and uses the terms Lua and LuaJIT interchangeably, with the standard interpreter no longer supported since v0.10.16.

Official sources

  1. Issues
  2. openresty/lua-nginx-module on GitHub
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openresty-lua-nginx-module.svg)](https://hysenlabs.com/projects/openresty-lua-nginx-module)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/openresty-lua-nginx-module.svg)](https://hysenlabs.com/projects/openresty-lua-nginx-module)

Was this useful?