Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

LuaadvancedbackendAI generated

OpenResty Rate Gate

Build a configurable rate limiting layer on OpenResty (Nginx with Lua) that protects your web services from being overwhelmed. Instead of one fixed limit, you write policies in a config file: for example, 100 requests per minute per IP for the public API, 10 login attempts per 15 minutes per username, and higher limits for clients with an API key. The gate matches each request to its policy, counts requests in memory shared by all Nginx workers, returns 429 with the standard headers when a limit is exceeded, and can reload its policies without restarting. You'll learn the Nginx request phases, shared dictionaries and atomic counters, rate limiting algorithms, designing a policy language, hot reloading configuration, and testing with Test::Nginx.

Estimate
~13h
Steps
7
Completed by
0
Proposed by
codeseed.app

LuaRocks · OpenResty

Project roadmap

  1. 01

    Design the policies

    ~2h

    Write DESIGN.md: a policy has a name, what it matches (path prefix and HTTP methods), what it counts by (IP, a header such as X-API-Key, or a request argument), the limit and window, the algorithm (fixed window or sliding window) and an optional burst. Decide the order in which policies apply when several match. Describe the response headers (X-RateLimit-Limit, Remaining and Reset, and Retry-After). Done when: DESIGN.md defines the policy format with examples.

  2. 02

    Set up OpenResty

    ~1.5h

    Run OpenResty in Docker with a small backend service. Declare lua_shared_dict zones for counters and policies, put your Lua code in modules loaded with lua_package_path, and load the policies from a JSON file in init_by_lua_block, validating them and refusing to start when they're invalid. Done when: OpenResty starts with valid policies and refuses invalid ones with a clear error.

  3. 03

    Count requests with shared memory

    ~2.5h

    In access_by_lua_block, find the matching policies, build a key for each (policy name plus the client identity), and count with the shared dictionary's atomic incr (with an initial value and an expiry). Implement the fixed window, and a sliding window that combines the current and previous window's counts. Done when: limits are enforced correctly no matter which worker handles a request.

  4. 04

    Respond and add headers

    ~1.5h

    When a limit is exceeded, return 429 with a JSON body naming the policy and the Retry-After header. On allowed requests, add the X-RateLimit headers for the strictest matching policy. Let an allow-list of IPs or keys skip limits. Done when: clients see accurate remaining counts and get 429 exactly when they go over.

  5. 05

    Reload policies safely

    ~2h

    Add a local-only admin endpoint that reloads the policy file: parse and validate the new file, and only if it's valid, store it in the shared dictionary with a version number that workers check, so all workers switch to the new policies. Keep the old policies when the new file is invalid. Done when: changing a limit in the file and calling the reload endpoint takes effect without restarting, and a broken file changes nothing.

  6. 06

    Handle memory limits and metrics

    ~1.5h

    Decide what happens when the shared dictionary is full (it evicts the oldest keys, which could reset counters), size it for your expected number of clients, and log a warning when evictions happen. Expose counts of allowed and limited requests per policy on a local-only /metrics endpoint. Done when: the metrics show traffic per policy, and memory behavior is documented.

  7. 07

    Test it

    ~2h

    Write tests with Test::Nginx (or a script using curl against the Docker setup): each policy's limit, windows resetting, the sliding window's smoothness at window edges, the allow-list, headers, policy order when several match, and reloading valid and invalid policies. Load test on your own machine with wrk to check the added latency. Done when: all tests pass, and README.md shows the latency cost.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~13h · 7 steps

Tech stack

LuaRocksOpenResty