Browse Source

docs: document nginx Lua layer and OpenResty future opportunity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rate-limiter-2026
Edward Ribeiro 6 days ago
parent
commit
a107846e7d
  1. 47
      plan/RATE-LIMITER-PLAN.md

47
plan/RATE-LIMITER-PLAN.md

@ -1614,6 +1614,53 @@ changes.
---
## nginx Lua layer — implementation notes
### Current stack: nginx + libnginx-mod-http-lua
`blocklist.lua` uses Debian's `libnginx-mod-http-lua` + `lua-resty-redis` packages. These are built against the same `nginx` version as `libnginx-mod-http-geoip2`, so all three modules are ABI-compatible and available for both `amd64` and `arm64`.
What the Lua layer does:
| Check | Mechanism | Redis I/O |
|-------|-----------|-----------|
| IP-prefix block | `ngx.shared.ip_prefix_blocked` dict (60 s refresh) | 0 per request |
| Global IP block | `GET rl:ip:{ip}:blocked` | pipelined |
| Per-tenant API block | `GET rl:api:ns:{ns}:ip:{ip}:blocked` | pipelined (1 round trip for both GETs) |
ASN blocking and UA blocking remain in nginx `if()` blocks (rewrite phase, before Lua access phase) — no Redis involved.
### Why OpenResty was not used
OpenResty was evaluated and rejected for this deployment:
1. **No arm64 Debian packages.** The `openresty.org/package/debian` repo publishes only `amd64`. Local Mac builds (Apple Silicon) and any future ARM node pools would need `--platform linux/amd64` + QEMU emulation.
2. **No functional difference for this use case.** The only OpenResty features beyond `libnginx-mod-http-lua` that were considered:
- *Bundled resty.* libraries* — all needed ones (`resty.redis`, `resty.core`, `resty.lrucache`) are in Debian packages.
- *OPM* — used only to install `lua-resty-maxminddb` for ASN lookups in Lua. Dropped when ASN blocking moved back to the GeoIP2 C module, which requires no OPM.
- *Slightly newer LuaJIT* — irrelevant at this workload.
### Future opportunity: migrate to OpenResty
Migration would be worth considering **only if** one of the following becomes a requirement:
| Trigger | Why it needs OpenResty |
|---------|----------------------|
| ASN lookup in Lua (remove GeoIP2 C module dependency) | Needs `lua-resty-maxminddb` via OPM; not in Debian repos |
| Per-request rate counting in nginx (move counters out of Django) | `resty.limit.req` / `resty.limit.conn` — not in Debian's lua packages |
| Cosocket-based upstream health checks or dynamic upstreams | OpenResty's `resty.upstream.*` ecosystem |
| JWT validation at nginx layer | `lua-resty-jwt` via OPM |
Migration steps when the time comes:
1. Add `--platform linux/amd64` to `docker build` (or use a multi-arch CI builder).
2. Replace `nginx libnginx-mod-http-geoip2 libnginx-mod-http-lua lua-resty-redis` with `openresty libmaxminddb0` + `opm get anjia0532/lua-resty-maxminddb`.
3. Update config paths: `/etc/nginx/``/usr/local/openresty/nginx/conf/`; binary `/usr/sbin/nginx``/usr/local/openresty/nginx/sbin/nginx`.
4. Replace `geoip2` C-module directives + `$bot_asn` map with `mmdb.lookup(ip)` in `blocklist.lua`.
5. Remove `lua_package_path` directive (OpenResty bundles all resty.* paths automatically).
---
## Open Questions
| # | Question | Status | Blocks |

Loading…
Cancel
Save