Library / SDK
openresty/redis2-nginx-module avatar
openresty/redis2-nginx-module

ngx_redis2: letting nginx talk to Redis 2.x without blocking

Nginx upstream module for the Redis 2.0 protocol

902 stars144 forksCLicense varies

At a glance

What is it?
ngx_redis2 is an OpenResty nginx module that speaks the full Redis 2.0 unified protocol, including pipelining, and returns the raw TCP response. It is written for deployments that already run nginx and Redis, and the documentation itself points at lua-resty-redis as the more flexible choice when Lua is available.
Who is it for?
ngx_redis2 suits a team running plain nginx and Redis 2.x that needs Redis access from the request path without adding a Lua layer, and the pipelining support makes it a reasonable fit for endpoint that issue several commands per request.
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 2 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 October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A module that returns the raw Redis reply

ngx_redis2 is described as an Nginx upstream module for the Redis 2.0 protocol, and the description section is specific about what it does. It makes nginx talk to a Redis 2.x server in a non-blocking way, and the full Redis 2.0 unified protocol has been implemented including the Redis pipelining support.

The design decision that shapes everything else is that the module returns the raw TCP response from the Redis server. Not a parsed value, not a JSON structure, the bytes as they came off the wire.

The documentation is direct about the consequence. It is recommended to use lua-redis-parser, written in pure C, to parse these responses into Lua data structures when combined with lua-nginx-module.

That is a deliberate division of labour. The module handles the protocol, the connection, the pooling and the non-blocking behaviour, and leaves the interpretation to whatever you already use for parsing. The alternative given in the documentation is to parse the Redis responses on the client side yourself.

So the audience is narrow and identifiable: an operator running nginx who needs Redis in the request path, and who has a preference for handling the response bytes directly rather than going through a Lua runtime. The repository is written in C, with the source under src/, a config directory, a t/ directory for tests, a misc/ and util/ directory, a Changes file and a valgrind.suppress file, which suggests a project that has been around long enough to accumulate the usual C project furniture.

The status section states that this module is already production ready, and the version section notes that the document describes v0.15, released on 19 April 2018. The last push was on 2026-10-18, so the tree is still being touched even though the documented release is from 2018.

The query directives and how pipelining works

The directive set is where the module's capabilities are visible, and there are four ways to write a query.

redis2_query takes a command and its arguments individually, in a way similar to the redis-cli utility, and is valid in the location and location if contexts. Multiple instances of this directive in a single location are allowed and the queries will be pipelined.

nginx
 location = /pipelined {
     redis2_query set hello world;
     redis2_query get hello;

     redis2_pass 127.0.0.1:$TEST_NGINX_REDIS_PORT;
 }

The documented result of a GET on that location is two successive raw Redis responses, and the documentation is careful that the newlines in the shown output are actually CR LF.

redis2_raw_query takes a raw query string and recognises Nginx variables in that argument, but only one Redis command is allowed in it or you receive an error. For multiple pipelined commands in a single directive, the documentation points to the next one.

redis2_raw_queries takes a count N and a queries string, and both arguments can take Nginx variables.

nginx
 location = /pipelined {
     redis2_raw_queries 3 "flushall\r\nget key1\r\nget key2\r\n";
     redis2_pass 127.0.0.1:6379;
 }

redis2_literal_raw_query is the variant where the dollar sign is not special, for sending a literal query with no variable interpolation.

The example in the synopsis shows the difference in one line. redis2_literal_raw_query takes '*1\r\n$4\r\nping\r\n' with a comment noting that $ is not special here, while redis2_raw_query takes 'get one\r\n' with the comment that variables can be used below and $ is special.

One dependency is called out repeatedly. The set_unescape_uri directive used in several examples comes from the set-misc-nginx-module, and the documentation says so each time it appears.

Timeouts, buffer size and the upstream failover directive

The remaining directives cover the operational surface, and they are the ones that matter when Redis is on the critical path.

There is redis2_connect_timeout, redis2_send_timeout and redis2_read_timeout, so the three phases of talking to an upstream are separately bounded. That granularity is the useful part. A connect timeout and a read timeout that share one value means you cannot distinguish a Redis that is unreachable from a Redis that is slow, and those need different responses.

redis2_buffer_size sets the buffer used for the upstream connection. redis2_next_upstream controls failover to the next upstream when one fails, which is what you want if you run a Redis replica set and want nginx to try the next node.

There is also a connection pool section in the documentation, along with sections on selecting Redis databases, Lua interoperability, Redis publish and subscribe support with a documented set of limitations, and performance tuning.

The Lua interoperability section is worth noting for its shape. The documentation describes pipelined Redis requests by Lua, which is the pattern where Lua code issues several Redis commands in one round trip rather than one call per command. The module supports issuing the requests and the Lua side assembles them, with the pipelining handled by the module rather than by Lua.

The publish and subscribe support carries its own limitations section, which the table of contents calls out separately. That is the right way to handle it, because pub/sub over a non-blocking upstream has constraints that the rest of the protocol does not, and a module that quietly dropped messages would be worse than one that documents the gap.

Every query directive is scoped to location and location if, and the redis2_pass directive supplies the upstream address, as in redis2_pass 127.0.0.1:6379.

When the documentation tells you to use something else

The most interesting part of this module's documentation is the advice it gives against using itself.

When used in conjunction with lua-nginx-module, it is recommended to use the lua-resty-redis library instead of this module, because the former is much more flexible and memory-efficient.

That is an unusual thing for a project's own documentation to say, and it tells you where the module sits in the ecosystem. The redis2 family of modules exists for nginx deployments that do not have the Lua runtime, or where pulling in Lua for the sake of a Redis client would be the wrong trade. In an OpenResty deployment, Lua is already there, lua-resty-redis is more capable, and adding a C module on top of that is redundant work.

The module makes a similar point about parsing. It recommends lua-redis-parser, written in pure C, to turn the raw responses into Lua data structures when combined with lua-nginx-module. So even in the case where you do use this module, the response handling is expected to happen in C or in Lua elsewhere, not inside nginx.

There is a narrower alternative too. If you only need the get command, the documentation points at the HttpRedisModule, which returns the parsed content part of the Redis response because only get is needed to implement. That module is the right choice for a simple key lookup in a template, and it gives you a parsed value instead of raw bytes.

The third option is to parse the responses on your client side yourself, which is what you do when the consumer is an application rather than nginx.

Taking these three recommendations together, the honest summary is that ngx_redis2 is the option for a plain nginx setup that needs something beyond get and does not want Lua. Everywhere else, the documentation is steering you to a different tool.

Installation, compatibility and what is not in the box

The installation note is short and specific: this module is not distributed with the Nginx source, and the installation instructions are linked separately.

That is normal for an OpenResty dynamic module, and the compatibility section covers which versions the module is built against. It is worth checking before you build, because the protocol implementation and the nginx API surface both move.

The repository layout shows the C project structure: src/ for the module source, config/ for the nginx module configuration, t/ for the test suite, misc/ and util/ for supporting files, a Changes file recording release history, and valgrind.suppress for suppressing known memory checker noise. That last file is a reasonable signal about the project's engineering standards, since it implies the code is run under a memory checker regularly enough to need a suppression list.

The project has the standard OpenResty community infrastructure around it, with English and Chinese mailing lists, a section for bugs and patches, and a source repository reference.

One structural point is worth stating plainly. The module name and the protocol version are bound together. This is a Redis 2.0 unified protocol implementation, and the documentation consistently describes a Redis 2.x server. Redis has moved on considerably since that protocol, and whether a modern Redis server still accepts the 2.0 style requests this module sends is exactly the kind of question the compatibility section should answer for you.

The module also ships no parsing, no connection pool implementation in your config and no Lua bindings of its own. It is a protocol and transport layer, and the documentation is unusually honest that the rest is your problem.

Where ngx_redis2 is the wrong choice

Three situations point away from this module.

The first is the OpenResty case. If your nginx is OpenResty, the documentation's own recommendation applies and you should use lua-resty-redis, which is more flexible and more memory efficient. Choosing ngx_redis2 there means adding a C module to a stack that already has a better answer.

The second is the simple get case. If all you want is to read one key and interpolate it into a template, the HttpRedisModule returns the parsed content and avoids the raw response handling entirely. That is less code and less to get wrong, and the raw bytes are a feature only if something downstream wants them.

The third is a modern Redis deployment. The module targets the Redis 2.0 unified protocol, and the documentation describes a Redis 2.x server. A Redis 6 or 7 deployment may well still speak a compatible dialect for the commands you need, but that is an assumption you have to verify against your own server rather than take from the readme, and the compatibility section is where to start.

The alternative approaches differ in what they cost. lua-resty-redis gives you parsed data and Lua control flow at the cost of the Lua runtime, which you usually already have in OpenResty. The HttpRedisModule gives you a parsed get and nothing else. Parsing on the client side gives you full control and full responsibility for the response format, and it is the right choice when the consumer is your own application rather than nginx. And the plain approach of having nginx proxy to an application that talks to Redis keeps the data path explicit, at the cost of an extra hop.

For the case this module fits, the fit is real: plain nginx, Redis 2.x, a need for pipelined commands, and a preference for handling the response bytes directly.

Editorial conclusion

ngx_redis2 suits a team running plain nginx and Redis 2.x that needs Redis access from the request path without adding a Lua layer, and the pipelining support makes it a reasonable fit for endpoint that issue several commands per request. It does not suit a Lua-based OpenResty deployment, because the documentation recommends lua-resty-redis there as more flexible and more memory efficient, and it does not suit a Redis 6 or later deployment since the protocol it implements is the 2.0 unified protocol. Before adopting it, check the Redis version on the other end, because the module name says Redis 2 and the implementation target is explicit, and read the compatibility section, which covers the versions the module is tested against.

Frequently asked questions

What does the ngx_redis2 nginx module do?

It makes nginx talk to a Redis 2.x server in a non-blocking way, implementing the full Redis 2.0 unified protocol including pipelining support. It returns the raw TCP response from the Redis server rather than a parsed value.

Which Redis commands can I send with ngx_redis2?

The redis2_query directive takes a command and its arguments individually, similar to redis-cli, and multiple instances in one location are pipelined. The redis2_raw_query directive takes a raw query with variable interpolation but allows only one command, while redis2_raw_queries takes a count N and a queries string, and redis2_literal_raw_query sends a query where the dollar sign is not special.

Should I use ngx_redis2 or lua-resty-redis?

If your nginx is OpenResty, the module documentation recommends lua-resty-redis instead, because it is much more flexible and memory-efficient. The documentation also recommends lua-redis-parser to parse the raw responses when you do use this module with lua-nginx-module.

How do I set timeouts when talking to Redis with ngx_redis2?

The three phases are configured separately, with redis2_connect_timeout, redis2_send_timeout and redis2_read_timeout, plus redis2_buffer_size for the connection buffer and redis2_next_upstream for failover to the next upstream. The upstream address itself is given with redis2_pass, for example redis2_pass 127.0.0.1:6379.

How is the ngx_redis2 module installed?

It is not distributed with the Nginx source, and the documentation points to separate installation instructions. The module is a dynamic nginx module with a compatibility section covering the versions it is built against, and the source is a C project with a test suite and a valgrind suppression file.

Official sources

  1. Issues
  2. openresty/redis2-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-redis2-nginx-module.svg)](https://hysenlabs.com/projects/openresty-redis2-nginx-module)

Was this useful?