Reduzer Technologies Training Institute
Our commitments
Online pilotApply
02
ReduzerPublic projectsProject 02
Sprint 3No. 02

Build rate limitermiddleware.

Implement reusable middleware with fixed window and token bucket algorithms, correct HTTP rejection signals, configurable route policies and a Redis-backed production store.

Go to project requirements

Duration

2 days

Format

Solo

Review

Required

Base brief

11 requirements

Token bucketFixed windowRedisHTTPMiddleware
BriefRequirementsInjectionsBuild planReview

Project summary

TYPE: BACKEND MIDDLEWARE LIBRARY
DURATION: 2 DAYS
DELIVERY: SOLO
REVIEW: MANDATORY PEER REVIEW

This page is the source of truth for the project. Where a summary and an acceptance criterion differ, follow the acceptance criterion.

Problem context

The APIs have no consistent protection against abusive callers.

You have joined a software team whose APIs keep getting overwhelmed. One client’s runaway script can hit an endpoint thousands of times per minute and degrade the service for everyone else. Scrapers and brute-force attempts go unchecked, and each service tries to solve the problem differently—or not at all. Production runs several service instances, so counters stored inside one process cannot enforce a global limit.

Required outcome

Build reusable rate-limiting middleware that caps requests per caller, rejects excess traffic with the correct HTTP status and headers, supports two algorithms, and remains correct when several service instances process concurrent requests through shared Redis state.

Architecture boundary

Required request path

The limiter must run before every protected route handler. It identifies the caller, loads the route policy, performs one atomic state decision using the selected store, and either forwards the request or returns 429 with correctly computed headers.

Required data path

  1. 01

    Request

    protected route

  2. 02

    Middleware

    before handler

  3. 03

    Identify

    caller key

  4. 04

    Policy

    algorithm + limit

  5. 05

    Atomic state

    memory / Redis

  6. 06

    Result

    handler / 429

Learning objectives

What the project is designed to assess

01

Implement and compare two rate-limiting algorithms

02

Design middleware with configurable caller and route policies

03

Coordinate distributed state through Redis

04

Guarantee correct decisions under concurrent requests

Base specification

Requirements

All acceptance criteria are mandatory unless an injected requirement explicitly changes them. Expand each requirement to read the complete criteria.

Phase 01

Middleware & fixed window

3 requirements

REQ-001Build the rate-limiting middlewareRun the limiting decision before a protected route handler and keep the implementation reusable across routes.

Acceptance criteria

  • The middleware runs before the route handler on every request to a protected route.
  • It can allow a request to continue to the handler.
  • It can stop a request and respond without the route handler running.
  • The same middleware is reusable across multiple routes.
  • Limiting logic is separated from route-handler logic.
REQ-002Identify the callerApply each allowance to a configurable caller identity and keep caller state isolated.

Acceptance criteria

  • Each caller’s usage is stored under a separate key.
  • The caller identifier is configurable and can use an IP address, API key or user ID.
  • Two different callers do not share an allowance.
  • The default identification key is documented.
REQ-003Implement the fixed window counter in memoryMaintain one counter per caller and fixed time window, then reset the allowance at the next window.

Acceptance criteria

  • Requests up to the configured limit are allowed within a window.
  • The request that exceeds the limit is rejected.
  • The caller’s allowance resets when the window ends.
  • The request limit and window duration are configurable.
  • Counts are maintained separately for each caller.

Phase 02

HTTP contract

1 requirements

REQ-004Reject with 429 and the correct headersReturn the standard HTTP signals clients need to understand and recover from a rejected request.

Acceptance criteria

  • A rejected request returns 429 Too Many Requests.
  • The response includes Retry-After telling the client when it may retry.
  • The response includes X-RateLimit-Remaining for the current allowance.
  • Header values are computed correctly for the selected algorithm: window reset for fixed window and token refill for token bucket.
  • Allowed requests never receive a 429 response.

Phase 03

Token bucket & route configuration

2 requirements

REQ-005Implement the token bucket in memoryUse lazy refill to support controlled bursts while enforcing a configured average rate over time.

Acceptance criteria

  • A request is allowed when a token is available and consumes one token.
  • A request is rejected when the caller’s bucket is empty.
  • Tokens refill over elapsed time up to the configured capacity.
  • An idle caller can make a burst up to the bucket capacity.
  • Over time, a caller cannot exceed the configured refill rate.
  • Capacity and refill rate are configurable.
REQ-006Configure the algorithm and limit per routeLet routes select an algorithm and limits without modifying the middleware’s internal implementation.

Acceptance criteria

  • A route can select fixed window or token bucket.
  • Every protected route can define its own limit values.
  • Different routes can use different algorithms and limits at the same time.
  • The behavior of an unconfigured route is documented.
  • Configuration does not require editing the middleware’s internal code.

Phase 04

Distributed state & Redis

2 requirements

REQ-007Document the distributed-state limitationExplain why process-local counters cannot enforce a global limit across several service instances.

Acceptance criteria

  • The README explains why in-memory storage fails when more than one service instance runs.
  • The explanation states that the effective limit multiplies approximately with the number of instances.
  • The README notes that in-memory state is lost on restart or deployment.
  • The README explains why production requires a shared store.
REQ-008Provide a Redis-backed production storePut limiter state in a shared store so all service instances enforce one global allowance.

Acceptance criteria

  • Both algorithms can use the Redis-backed store.
  • Separate service instances share counts for the same caller.
  • The storage backend is selectable between in-memory and Redis using configuration.
  • The Redis connection is configurable and not hardcoded.
  • The README explains how to run the middleware against Redis.

Phase 05

Concurrency safety

1 requirements

REQ-009Make counting correct under concurrencyExecute each check-and-update as one atomic operation so overlapping requests cannot over-admit.

Acceptance criteria

  • Concurrent requests from one caller never admit more than the configured limit.
  • The read, decision and update for one request execute atomically.
  • The atomic guarantee holds for both algorithms, including multi-step decisions.
  • The outcome is the same for sequential requests and requests arriving at once.
  • Concurrency simulation tests demonstrate the guarantee.

Phase 06

Tests & documentation

2 requirements

REQ-010Add concurrency simulation & edge-case testsProve both algorithms remain within their limits under overlapping load and boundary conditions.

Acceptance criteria

  • A simulation fires many overlapping requests for one caller and asserts that the configured limit is never exceeded.
  • The concurrency simulation covers fixed window and token bucket.
  • Fixed window, token bucket, headers, per-route configuration and the Redis store each have at least five edge-case tests.
  • Tests include allowed and rejected cases.
  • The command used to run the tests is documented.
REQ-011Provide README.mdDocument the middleware for another developer who needs to install, configure, run and evaluate it.

Acceptance criteria

  • The README explains what the middleware does.
  • It shows how to protect a route and configure its algorithm and limits.
  • It documents the response headers.
  • It explains the in-memory and Redis options and the distributed-state limitation.
  • It shows how to run all tests, including the concurrency simulation.
  • It includes at least three usage examples.

Injected requirements

Scheduled changes to the specification

Additional requirements are released during the project. Once a requirement is released, it becomes mandatory and is included in the grading criteria. Check this section at the indicated release time.

Mid-sprint requirement injection

Unlocks after 24 hours

The requirement details remain hidden until after 24 hours. Continue with the base specification until this section unlocks.

Release schedule coming soon

Release times are calculated from the public campaign start date. All participants receive each injected requirement at the same time.

Technical rules

Technical constraints

These constraints are assessed alongside functional behavior. A solution that bypasses them does not meet the specification.

  1. 01Do not use an external rate-limiting library for the core logic. Framework middleware and a Redis client are allowed.
  2. 02Implement both token bucket and fixed window counter algorithms.
  3. 03Configure the algorithm and limits per route; do not hardcode them.
  4. 04Use Redis as the production store; in-memory storage is only the single-instance option.
  5. 05Perform every check-and-update atomically so concurrent requests cannot over-admit.
  6. 06Return correctly computed 429, Retry-After and X-RateLimit-Remaining values.
  7. 07Run the limiter as middleware before route handlers.
  8. 08Include the required concurrency simulations and edge-case tests.
  9. 09Document the middleware and explicitly explain the distributed-state limitation.

Suggested build order

Suggested 2-day build order

You may use a different sequence, but all requirements, tests, documentation and peer review are due by the end of Day 7.

Day 1 · First

01 / 06

Middleware & fixed window

  • Create the middleware boundary and configurable caller key.
  • Implement the in-memory fixed window counter.
  • Prove that the limit rejects and the next window resets.
Day 1 · Next

02 / 06

HTTP contract

  • Return 429 for rejected requests.
  • Compute Retry-After and X-RateLimit-Remaining correctly.
Day 1 · Then

03 / 06

Token bucket & per-route policies

  • Add lazy token refill, capacity and refill rate.
  • Make algorithm and limits selectable per route.
Day 2 · First

04 / 06

Distributed state

  • Document why in-memory counters fail across instances.
  • Move both algorithms behind a configurable Redis store.
Day 2 · Next

05 / 06

Atomicity & concurrency

  • Make each algorithm’s check-and-update atomic.
  • Run overlapping-request simulations and edge-case tests.
After injection

06 / 06

Runtime allowlist & review

  • Implement the released allowlist requirements.
  • Complete the README, examples and mandatory peer review.

Submission checklist

Required deliverables

The implementation alone is not a complete submission. Provide the following evidence so another engineer can run, test and evaluate the system.

  1. 01A public repository containing reusable rate-limiting middleware.
  2. 02Working fixed window and token bucket implementations with selectable in-memory and Redis stores.
  3. 03Per-route configuration for caller identity, algorithm and limits.
  4. 04Automated edge-case tests and concurrency simulations for both algorithms.
  5. 05A README containing every required section and at least three usage examples.
  6. 06Evidence showing correct 429, Retry-After and X-RateLimit-Remaining behavior.
  7. 07A completed peer review with findings and the changes made afterward.

Documentation structure

README.md must include

Use these headings so another developer can find every required explanation and command.

  1. 01# Rate Limiter Middleware
  2. 02## What This Middleware Does
  3. 03## Installation
  4. 04## Running Tests
  5. 05## Protecting a Route
  6. 06## Configuring Limits Per Route
  7. 07## Choosing an Algorithm (Token Bucket vs Fixed Window)
  8. 08## The Response Headers
  9. 09## In-Memory vs Redis (and the Distributed-State Limitation)
  10. 10## Running the Concurrency Tests
  11. 11## The Allowlist
  12. 12## Known Limitations

Evaluation

Grading criteria

Algorithm correctness25%
Concurrency safety20%
Distributed-state handling15%
HTTP header correctness15%
Per-route configuration & middleware design10%
Concurrency simulation & edge-case testing10%
README documentation5%

Mandatory peer review

Assessment questions

The reviewer should ask these questions and inspect the code, tests and runtime evidence supporting each answer. Record the findings and the changes made after review.

  1. 01What is the boundary burst problem in fixed window, and does token bucket suffer from it?
  2. 02How does token bucket allow a burst while enforcing an average rate over time?
  3. 03Why does in-memory state fail when the service runs more than one instance?
  4. 04How does the Redis-backed store make the limit global again?
  5. 05What race condition exists in a check-then-update, and how does it cause over-admission?
  6. 06How is each algorithm’s check-and-update made atomic, including decisions requiring several steps?
  7. 07What does each response header mean, and how does Retry-After differ between the algorithms?
  8. 08Which caller identifier is used, and what are the trade-offs of IP, API key and user ID?
  9. 09How does a route choose its algorithm and limit?
  10. 10How do the concurrency simulations prove that the limiter never over-admits?

Participation and peer review

Publish the implementation evidence

Use a public repository. Post the architecture, important trade-offs, test results, performance evidence and final demo. Ask another developer to complete the required peer review. Tag @reduzer_tech so Reduzer can find the submission.

Start with REQ-001Create a repository
01

Declare your approach

Document the language, architecture, configuration and main risks before implementation.

02

Post evidence

Publish commits, test output, throughput results, metrics and dashboard evidence.

03

Invite review

Have another developer inspect the failure paths, record their findings and document your fixes.

Next project

More public engineering briefs are coming.

View the project series
Reduzer Technologies Training Institute

Reduzer Technologies Training Institute

Programme

  • Public projects
  • Fit and readiness
  • Graduate capability
  • How it works
  • Programme
  • Online pilot
  • Our commitments
  • Why Kisii
  • Cost

Admissions

  • Parents and sponsors
  • Sponsor a student
  • Admissions process
  • Apply for the in-person programme
  • Apply for the online pilot
  • FAQ

Contact admissions

Parents and sponsors can confirm fees, intake dates, seat availability, expectations, and support arrangements before committing.

Call +254 769 267 965Message admissions on WhatsAppEmail hello@reduzer.ac.ke

© 2026 Reduzer Technologies Limited

In person and online · Starts 5 October 2026

  • Privacy policy
  • Terms of service
  • Cookie policy