networking · intermediate · ~15 min

Token-bucket rate limiter (single slot)

Token-bucket rate limiting, a defensive shield against brute force.

Challenge

Implement a single-slot token-bucket rate limiter — the smoothing technique behind rate-limited APIs and brute-force defenses.

Task

Given the bucket struct (defined by the harness):

typedef struct { double tokens; double rate; double max; double last_refill; } bucket_t;

implement int rl_allow(bucket_t *b, double now) that decides whether one request is allowed at time now. It must:

  1. Refill: add rate * (now - last_refill) tokens, capped at max.
  2. Update last_refill = now.
  3. If tokens >= 1.0, consume one token and return 1; otherwise return 0.

Input

  • b: the bucket (carries current tokens, refill rate per unit time, max capacity, and last_refill timestamp).
  • now: the current time, in the same units as rate and last_refill.

Output

Return 1 if a token was available and consumed (request allowed), else 0 (request denied). The bucket is updated in place.

Example

b = {tokens:0, rate:1, max:3, last_refill:0}
rl_allow(&b, 0.0)  ->  0   (no tokens yet)
rl_allow(&b, 1.0)  ->  1   (1s elapsed -> 1 token, consumed)
rl_allow(&b, 1.0)  ->  0   (no time passed, bucket empty)
rl_allow(&b, 5.0)  ->  1   (refill capped at max=3, one consumed)

Edge cases

  • Refilled tokens never exceed max.
  • Calling twice at the same now adds no tokens the second time.

Input format

b: the bucket struct (tokens, rate, max, last_refill); now: current time.

Output format

1 if a token was available and consumed (allowed), else 0; b is updated in place.

Constraints

tokens points to current token count; rate and cap are positive integers; elapsed_ms is non-negative.

Starter code

#include <stdio.h>
int rl_allow(bucket_t *b, double now) { /* TODO */ return 0; }

Common mistakes

Allowing tokens to exceed capacity or underflowing token count when denying request.

Edge cases to handle

Zero elapsed time, bucket at capacity, rapid requests exhausting bucket.

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.