Rate Limiter with Separate Limits for Each Field of a Multi-Field Request

Quick Overview

Implement a rate limiter that decides per key whether a request is allowed, then extend it so a request with several fields, such as a user and an IP address, is limited on each field separately. It tests window semantics, per-key state and cleanup, all-or-nothing updates across fields, and concurrency.

Rate Limiter with Separate Limits for Each Field of a Multi-Field Request

Company: Roblox

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Technical Screen

Implement a rate limiter, then extend it so that a request carrying several fields is rate-limited on each field separately. The report describes a 45-minute screen covering both parts on a tight clock, and it does not restate the exact limiting rule of the first part, so agree on the interface and the rule with the interviewer quickly. ### Constraints and Clarifications - Not given: the limiting algorithm, the limits and windows, whether time is passed in or read from a clock, and whether the limiter is shared across threads or servers. Ask, or state your assumptions. ### Clarifying Questions - What does a limit mean: at most a number of requests per key in a time window, or a sustained rate that allows bursts? If a window, is it aligned to clock boundaries or sliding? - Is the time of each request passed in by the caller, or read from a clock? Can times arrive out of order? - Does a rejected request count toward the limit? - Is the answer only allow or deny, or should the caller also learn when to retry? - One process or many servers? Is the limiter called from several threads? - How many distinct keys are expected, and must keys that go idle be cleaned up? ### Part 1 — Rate limiter Implement a rate limiter with a method that, given a key (for example a client id) and the time of a request, decides whether to allow the request. ```hint What must be remembered For the rule you agreed, work out the least state per key that still decides the next request exactly, and when that state can be thrown away. ``` #### What This Part Should Cover - A precise rule, including what happens to a request exactly at the window boundary - Per-key state, its memory cost, and cleanup of idle keys - Time and space complexity per request - Tests driven by explicit timestamps, including the boundary ### Part 2 — Separate limits for each field Requests now carry several fields, for example a user id, an IP address and an endpoint (illustrative). Each field has its own limit, and the limiter must enforce the limit of every field separately. ```hint Partial success Take a request that is within the limit for two fields but over it for the third. Decide what should happen to the first two fields' counts, and make sure your code cannot leave them half-updated. ``` #### Clarifying Questions for this Part - Is the request allowed only when it is within the limit on every field, or is each field's decision reported on its own? - When a request is rejected because of one field, does it still use up quota on the other fields? - Can a field be missing from a request? Can limits differ per field, or per value of a field? #### What This Part Should Cover - A configuration that maps each field to its limit and reuses the Part 1 limiter - An all-or-nothing check-then-record step and its behavior under concurrent calls - What the caller is told on rejection: which field, and when to retry - Cost per request as the number of fields grows ### What a Strong Answer Covers - Settles the limiting rule, time source and rejection semantics before coding - Exact window-boundary behavior, tested with injected timestamps - Bounded per-key memory with cleanup of idle keys - Correct multi-field semantics with no partial updates, including under concurrent calls - Knows the main limiting algorithms and the trade-offs between exactness, memory and burst behavior ### Follow-up Questions - The limits must now hold across many servers. Where does the state live, and how do you keep the multi-field check atomic? - One limit applies to a combination of fields, such as one user on one endpoint. How does your configuration express it? - A key's limit is tens of thousands of requests per window. What does that do to your memory, and what would you change? - How would you tell a rejected client when to retry?

Overview: Implement a rate limiter that decides per key whether a request is allowed, then extend it so a request with several fields, such as a user and an IP address, is limited on each field separately. It tests window semantics, per-key state and cleanup, all-or-nothing updates across fields, and concurrency.

Roblox logo
Roblox
Oct 28, 2026
mediumSoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

Implement a rate limiter, then extend it so that a request carrying several fields is rate-limited on each field separately. The report describes a 45-minute screen covering both parts on a tight clock, and it does not restate the exact limiting rule of the first part, so agree on the interface and the rule with the interviewer quickly.

Constraints and Clarifications

  • Not given: the limiting algorithm, the limits and windows, whether time is passed in or read from a clock, and whether the limiter is shared across threads or servers. Ask, or state your assumptions.

Clarifying Questions Guidance

  • What does a limit mean: at most a number of requests per key in a time window, or a sustained rate that allows bursts? If a window, is it aligned to clock boundaries or sliding?
  • Is the time of each request passed in by the caller, or read from a clock? Can times arrive out of order?
  • Does a rejected request count toward the limit?
  • Is the answer only allow or deny, or should the caller also learn when to retry?
  • One process or many servers? Is the limiter called from several threads?
  • How many distinct keys are expected, and must keys that go idle be cleaned up?

Part 1 — Rate limiter

Implement a rate limiter with a method that, given a key (for example a client id) and the time of a request, decides whether to allow the request.

What This Part Should Cover Guidance

  • A precise rule, including what happens to a request exactly at the window boundary
  • Per-key state, its memory cost, and cleanup of idle keys
  • Time and space complexity per request
  • Tests driven by explicit timestamps, including the boundary

Part 2 — Separate limits for each field

Requests now carry several fields, for example a user id, an IP address and an endpoint (illustrative). Each field has its own limit, and the limiter must enforce the limit of every field separately.

Clarifying Questions for this Part Guidance

  • Is the request allowed only when it is within the limit on every field, or is each field's decision reported on its own?
  • When a request is rejected because of one field, does it still use up quota on the other fields?
  • Can a field be missing from a request? Can limits differ per field, or per value of a field?

What This Part Should Cover Guidance

  • A configuration that maps each field to its limit and reuses the Part 1 limiter
  • An all-or-nothing check-then-record step and its behavior under concurrent calls
  • What the caller is told on rejection: which field, and when to retry
  • Cost per request as the number of fields grows

What a Strong Answer Covers Guidance

  • Settles the limiting rule, time source and rejection semantics before coding
  • Exact window-boundary behavior, tested with injected timestamps
  • Bounded per-key memory with cleanup of idle keys
  • Correct multi-field semantics with no partial updates, including under concurrent calls
  • Knows the main limiting algorithms and the trade-offs between exactness, memory and burst behavior

Follow-up Questions Guidance

  • The limits must now hold across many servers. Where does the state live, and how do you keep the multi-field check atomic?
  • One limit applies to a combination of fields, such as one user on one endpoint. How does your configuration express it?
  • A key's limit is tens of thousands of requests per window. What does that do to your memory, and what would you change?
  • How would you tell a rejected client when to retry?