← Headway Interview Insights

Headway·Software Engineer·Online Assessment (OA)·Intermediate

IntermediatePrefer not to say
Jun 2026Remote

Summary

Headway gave me a CodeSignal assessment for a Software Engineer role where the whole thing was one big rate-limiting implementation task. No LeetCode puzzles, just a real-ish project with threading concerns and window semantics to figure out.

Questions Asked (1)

Q1

You're given a REST API skeleton. Add rate-limiting middleware that enforces a global limit of 100 requests per minute and a per-endpoint limit of 3 requests per second, returning 429 when either is exceeded. Use a fixed-window approach and make sure the limiter wraps all handlers automatically.

System DesignAPI & IntegrationsTechnical Trade-offs
Author's notes

The fixed-window part tripped me up more than I expected.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, then outline a middleware-based solution using fixed-window counters for both global and per-endpoint limits. Explain how to integrate the middleware to wrap all handlers automatically, and discuss trade-offs and edge cases.

Pro tip: Mention that fixed-window can allow bursts at window boundaries, and briefly note alternatives like sliding-window or token bucket for more precise limiting. Also, emphasize the importance of atomic operations for counters in concurrent environments.

1. Clarify requirements and constraints

Confirm the scope: global limit of 100 requests per minute and per-endpoint limit of 3 requests per second, using fixed-window. Ask about expected traffic, distributed vs. single-instance deployment, and whether limits should be per-user or global.

2. Design the rate-limiting middleware

Propose a middleware that intercepts all requests, identifies the endpoint (e.g., by route pattern), and checks both global and per-endpoint counters. Use in-memory counters with timestamps for fixed windows, and return 429 if either limit is exceeded.

3. Implement counter logic and atomicity

For each window, maintain a counter and window start time. Use atomic operations or locks to increment counters safely. Reset counters when the window expires. Ensure per-endpoint counters are keyed by a normalized endpoint identifier.

4. Integrate middleware to wrap all handlers

Apply the middleware globally so it runs before every request handler. In frameworks like Express, use app.use(); in others, use a similar global hook. Ensure it doesn't interfere with static assets or health checks if not desired.

5. Discuss trade-offs and extensions

Acknowledge fixed-window's burst issue at boundaries. Mention that for distributed systems, a centralized store like Redis is needed. Suggest monitoring and logging for rate-limit hits, and consider returning Retry-After headers.

Key Points to Mention

  • Fixed-window algorithm: simple but allows bursts at window edges.
  • Middleware pattern: wraps all handlers automatically via global registration.
  • Atomic counters: use locks or atomic operations to handle concurrency.
  • Per-endpoint identification: normalize routes (e.g., /users/:id) to avoid unbounded keys.
  • 429 response: include Retry-After header to indicate when to retry.
  • Scalability: for distributed systems, use a shared store like Redis with atomic increments.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.