Refund Rate Limiter for Merchants
Design an in-memory rate limiter that controls how frequently each merchant can initiate refunds.
Rate Limit Rule
Each merchant may initiate at most maxRefunds refunds within any rolling 5-minute window.
- Rate limits are tracked independently for each merchant.
- A rolling 5-minute window contains the previous
300,000 milliseconds.
- A previously allowed refund with timestamp less than or equal to
timestamp - 300,000 is outside the current window.
- Only allowed refunds count toward the rate limit.
- A rejected refund request must not be recorded.
Class Initialization
RefundRateLimiter(int maxRefunds)
Parameters
maxRefunds: The maximum number of refunds that one merchant may initiate during a rolling 5-minute window.
Method Signature
boolean allowRefund(String merchantId, long timestamp)
Parameters
merchantId: The unique identifier of the merchant requesting the refund.
timestamp: The refund request time in milliseconds.
Returns
- Return
true when the merchant has initiated fewer than maxRefunds refunds during the current rolling 5-minute window.
- Return
false when the merchant has already reached the limit.
Data Structure Requirements
Use an in-memory mapping from each merchant ID to the timestamps of that merchant's allowed refunds. Expired timestamps should be removed before deciding whether a new refund is allowed.
Constraints
1 ≤ maxRefunds ≤ 100,000
1 ≤ merchantId.length() ≤ 100
0 ≤ timestamp ≤ 1,000,000,000
- Calls for the same
merchantId are made in non-decreasing timestamp order.
merchantId is never empty.
Examples
Example 1
RefundRateLimiter(maxRefunds = 2)
allowRefund(merchantId = "store-17", timestamp = 10,000) returns true.
allowRefund(merchantId = "store-17", timestamp = 20,000) returns true.
allowRefund(merchantId = "store-17", timestamp = 30,000) returns false.
The merchant already has two allowed refunds within the current rolling 5-minute window.
Example 2
RefundRateLimiter(maxRefunds = 2)
allowRefund(merchantId = "merchant-a", timestamp = 1,000) returns true.
allowRefund(merchantId = "merchant-a", timestamp = 2,000) returns true.
allowRefund(merchantId = "merchant-b", timestamp = 3,000) returns true.
Each merchant has an independent refund limit.
Example 3
RefundRateLimiter(maxRefunds = 1)
allowRefund(merchantId = "shop-9", timestamp = 50,000) returns true.
allowRefund(merchantId = "shop-9", timestamp = 349,999) returns false.
allowRefund(merchantId = "shop-9", timestamp = 350,000) returns true.
At timestamp 350,000, the refund recorded at timestamp 50,000 is exactly 5 minutes old and is removed from the active window.