{"id":13578576,"url":"https://github.com/leandromoreira/nginx-lua-redis-rate-measuring","last_synced_at":"2026-03-02T23:31:38.796Z","repository":{"id":76830107,"uuid":"167376423","full_name":"leandromoreira/nginx-lua-redis-rate-measuring","owner":"leandromoreira","description":"A lua library to provide distributed rate measurement using nginx + redis, you can use it to do a throttling system within many nodes.","archived":false,"fork":false,"pushed_at":"2023-09-04T14:20:29.000Z","size":148,"stargazers_count":154,"open_issues_count":3,"forks_count":16,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-04T01:34:56.519Z","etag":null,"topics":["distributed-systems","lua","measurements","nginx","rate-limit","rate-limiter","redis","redis-cluster","throttle"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leandromoreira.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-01-24T13:59:20.000Z","updated_at":"2025-09-26T19:28:07.000Z","dependencies_parsed_at":"2024-01-16T20:29:25.377Z","dependency_job_id":"8e594f8a-5c80-4765-8f95-27a940fec2e0","html_url":"https://github.com/leandromoreira/nginx-lua-redis-rate-measuring","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/leandromoreira/nginx-lua-redis-rate-measuring","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoreira%2Fnginx-lua-redis-rate-measuring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoreira%2Fnginx-lua-redis-rate-measuring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoreira%2Fnginx-lua-redis-rate-measuring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoreira%2Fnginx-lua-redis-rate-measuring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leandromoreira","download_url":"https://codeload.github.com/leandromoreira/nginx-lua-redis-rate-measuring/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leandromoreira%2Fnginx-lua-redis-rate-measuring/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30025024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T23:03:42.610Z","status":"ssl_error","status_checked_at":"2026-03-02T23:00:47.223Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed-systems","lua","measurements","nginx","rate-limit","rate-limiter","redis","redis-cluster","throttle"],"created_at":"2024-08-01T15:01:31.946Z","updated_at":"2026-03-02T23:31:38.775Z","avatar_url":"https://github.com/leandromoreira.png","language":"Lua","funding_links":[],"categories":["Lua"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/leandromoreira/nginx-lua-redis-rate-measuring.svg?branch=master)](https://travis-ci.org/leandromoreira/nginx-lua-redis-rate-measuring) [![license](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg) [![Coverage Status](https://coveralls.io/repos/github/leandromoreira/nginx-lua-redis-rate-measuring/badge.svg)](https://coveralls.io/github/leandromoreira/nginx-lua-redis-rate-measuring)\n\n# Resty Redis Rate\n\nA [Lua](https://www.lua.org/) library providing rate measurement using [nginx](https://nginx.org/) + Redis. This lib was inspired on Cloudflare's post [How we built rate limiting capable of scaling to millions of domains.](https://blog.cloudflare.com/counting-things-a-lot-of-different-things/)\n\n\u003e You can found more about why and when this library was created [here.](https://leandromoreira.com.br/2019/01/25/how-to-build-a-distributed-throttling-system-with-nginx-lua-redis/).\n\n# Use case: distributed throttling\n\nNginx has already [a rate limiting feature](https://www.nginx.com/blog/rate-limiting-nginx/) but it is restricted by the local node. Once you have more than one server behind a load balancer this won't work as expected, so you can use [redis](https://redis.io/) as a distributed storage to keep the rating data.\n\n```lua\nlocal redis_client = redis_cluster:new(config)\n-- let's say we'll use the ?token=\u003cvalue\u003e as the key to rate limit\nlocal rate, err = redis_rate.measure(redis_client, ngx.var.arg_token)\nif err then\n    ngx.log(ngx.ERR, \"err: \", err)\n    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)\nend\n\n-- once we hit more than 10 reqs/m we'll reply 403\nif rate \u003e 10 then\n    ngx.exit(ngx.HTTP_FORBIDDEN)\nend\n\nngx.say(rate)\n```\n\n### Tests result\n\nWe ran three different experiments constrained by a `rate limit of 10 req/minute`:\n\n1.  `Experiment1:` 1 reqs/second\n1.  `Experiment2:` 1/6 reqs/second\n1.  `Experiment3:` 1/5 reqs/second\n\n![nginx redis throttling exprimentes graph result](/img/graph.png \"A graph with experiments results\")\n\n\u003e All the data points above the rate limit (the red line) resulted in forbidden responses.\n\nYou can run the throttling example locally, open up a terminal tab to run the servers.\n\n\u003e **Make sure you have `docker` and `docker-compose` installed.**\n\n```bash\nmake up\n```\nOpen another terminal tab and perform the experiments:\n\n```bash\n# Experiment 1\nfor i in {1..120}; do curl \"http://localhost:8080/lua_content?token=Experiment1\" \u0026\u0026 sleep 1; done\n\n# Experiment 2\nfor i in {1..20}; do curl \"http://localhost:8080/lua_content?token=Experiment2\" \u0026\u0026 sleep 6; done\n\n# Experiment 3\nfor i in {1..24}; do curl \"http://localhost:8080/lua_content?token=Experiment3\" \u0026\u0026 sleep 5; done\n```\n\n# Pipeline and hash tag\n\nWe're using the combination of [pipeline](https://redis.io/topics/pipelining) and [hash tag](https://redis.io/topics/cluster-spec#keys-hash-tags) to perform all the commands in a single connection to redis cluster. You can see the tcpdump output showing the [three-way handshake](https://en.wikipedia.org/wiki/Handshaking#TCP_three-way_handshake) followed by the three commands requests `$get`, `$inc` and `$expire` and the redis response.\n\n```bash\n22:20:10.515457 IP (tos 0x0, ttl 64, id 38199, offset 0, flags [DF], proto TCP (6), length 60)\n    172.31.0.3.49824 \u003e 172.31.0.2.7000: Flags [S], cksum 0x5872 (incorrect -\u003e 0xb9b9), seq 1010830934, win 29200, options [mss 1460,sackOK,TS val 170849 ecr 0,nop,wscale 7], length 0\n\n22:20:10.515505 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n    172.31.0.2.7000 \u003e 172.31.0.3.49824: Flags [S.], cksum 0x5872 (incorrect -\u003e 0xfcda), seq 1496303914, ack 1010830935, win 28960, options [mss 1460,sackOK,TS val 170849 ecr 170849,nop,wscale 7], length 0\n\n22:20:10.515518 IP (tos 0x0, ttl 64, id 38200, offset 0, flags [DF], proto TCP (6), length 52)\n    172.31.0.3.49824 \u003e 172.31.0.2.7000: Flags [.], cksum 0x586a (incorrect -\u003e 0x9be2), seq 1, ack 1, win 229, options [nop,nop,TS val 170849 ecr 170849], length 0\n\n22:20:10.515648 IP (tos 0x0, ttl 64, id 38201, offset 0, flags [DF], proto TCP (6), length 212)\n    172.31.0.3.49824 \u003e 172.31.0.2.7000: Flags [P.], cksum 0x590a (incorrect -\u003e 0x7954), seq 1:161, ack 1, win 229, options [nop,nop,TS val 170849 ecr 170849], length 160\n\t0x0000:  4500 00d4 9539 4000 4006 4ca7 ac1f 0003  E....9@.@.L.....\n\t0x0010:  ac1f 0002 c2a0 1b58 3c40 0e57 592f c92b  .......X\u003c@.WY/.+\n\t0x0020:  8018 00e5 590a 0000 0101 080a 0002 9b61  ....Y..........a\n\t0x0030:  0002 9b61 2a32 0d0a 2433 0d0a 6765 740d  ...a*2..$3..get.\n\t0x0040:  0a24 3239 0d0a 6e67 785f 7261 7465 5f6d  .$29..ngx_rate_m\n\t0x0050:  6561 7375 7269 6e67 5f7b 6c75 6967 697d  easuring_{luigi}\n\t0x0060:  5f31 390d 0a2a 320d 0a24 340d 0a69 6e63  _19..*2..$4..inc\n\t0x0070:  720d 0a24 3239 0d0a 6e67 785f 7261 7465  r..$29..ngx_rate\n\t0x0080:  5f6d 6561 7375 7269 6e67 5f7b 6c75 6967  _measuring_{luig\n\t0x0090:  697d 5f32 300d 0a2a 330d 0a24 360d 0a65  i}_20..*3..$6..e\n\t0x00a0:  7870 6972 650d 0a24 3239 0d0a 6e67 785f  xpire..$29..ngx_\n\t0x00b0:  7261 7465 5f6d 6561 7375 7269 6e67 5f7b  rate_measuring_{\n\t0x00c0:  6c75 6967 697d 5f32 300d 0a24 330d 0a31  luigi}_20..$3..1\n\t0x00d0:  3230 0d0a                                20..\n22:20:10.517337 IP (tos 0x0, ttl 64, id 21067, offset 0, flags [DF], proto TCP (6), length 65)\n    172.31.0.2.7000 \u003e 172.31.0.3.49824: Flags [P.], cksum 0x5877 (incorrect -\u003e 0xc55e), seq 1:14, ack 161, win 235, options [nop,nop,TS val 170849 ecr 170849], length 13\n\t0x0000:  4500 0041 524b 4000 4006 9028 ac1f 0002  E..ARK@.@..(....\n\t0x0010:  ac1f 0003 1b58 c2a0 592f c92b 3c40 0ef7  .....X..Y/.+\u003c@..\n\t0x0020:  8018 00eb 5877 0000 0101 080a 0002 9b61  ....Xw.........a\n\t0x0030:  0002 9b61 242d 310d 0a3a 310d 0a3a 310d  ...a$-1..:1..:1.\n\t0x0040:  0a                                       .\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandromoreira%2Fnginx-lua-redis-rate-measuring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleandromoreira%2Fnginx-lua-redis-rate-measuring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandromoreira%2Fnginx-lua-redis-rate-measuring/lists"}