Build and Review a Configurable Node.js Token-Bucket Rate Limiter
Company: Okta
Role: Backend Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
Build a Node.js Express application that reads a configuration file and exposes an API governed by a token-bucket rate limiter. Then explain the implementation's architecture as if reviewing the submitted code with another engineer.
### Constraints & Assumptions
- Use the token-bucket algorithm, with a configured capacity and token refill rate.
- The application must read configuration from a file and return an appropriate allowed or rate-limited API response.
- Practice clarification: implement one initially full, in-memory bucket for one endpoint in one Node.js process. Each request costs one token. This makes the unspecified bucket scope explicit; discuss how changing the scope affects the architecture.
- Invalid configuration should prevent the service from starting. No persistence or multi-process coordination is assumed for the initial implementation.
### Clarifying Questions to Ask
- Is a bucket shared by the endpoint or assigned per user, API key, or client address?
- Should bursts up to capacity be allowed immediately, and should unused tokens accumulate only up to capacity?
- Does a denied request consume tokens? What response should tell a caller when another attempt may succeed?
### What a Strong Answer Covers
- Lazy refill based on elapsed time, capped capacity, and an atomic check-and-consume operation within the process.
- Configuration parsing and validation, separation of the limiter from Express, and meaningful HTTP responses.
- A clock choice that is not disrupted by wall-clock corrections.
- Tests using a controllable clock for exhaustion, refill, and long idle periods.
- An explanation of the boundaries of an in-memory design when instances or bucket identities multiply.
```hint Account for idle time without a refill timer
Track the previous accounting time and compute the tokens earned since then when the next request arrives.
```
### Follow-up Questions
- Why is the limiter state transition safe within one event loop, and what change would make that reasoning invalid?
- How would you prevent a client from obtaining a fresh full bucket simply by reaching another server instance?
- If buckets become per-user, how would you bound the memory used by inactive buckets?
Overview: Implement a configurable Node.js Express token-bucket rate limiter with monotonic refill, HTTP 429 responses, code-review reasoning, and multi-instance limits.
Read the full Okta Backend Engineer interview experience this question came from