Rate Limit

What it is

Rate limit restricts how many executions can occur within a time window. Excess calls either wait or fail, depending on the strategy.

When to use it

  • API clients that must respect a server’s rate limit.
  • Sending notifications or emails without overwhelming the provider.
  • Throttling high-frequency user actions.

Async / sync support

WrapperSupport
Func<R>✅ Async
Func1<T, R>✅ Async
Func2<T1, T2, R>✅ Async
FuncSync<R>❌ No

API reference

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// api-reference
// On Func<R>
Func<R> rateLimit({
  required int maxCalls,
  required Duration window,
  RateLimitStrategy strategy = RateLimitStrategy.queue,
});

// On Func1<T, R>
Func1<T, R> rateLimit({
  required int maxCalls,
  required Duration window,
  RateLimitStrategy strategy = RateLimitStrategy.queue,
});

// On Func2<T1, T2, R>
Func2<T1, T2, R> rateLimit({
  required int maxCalls,
  required Duration window,
  RateLimitStrategy strategy = RateLimitStrategy.queue,
});

enum RateLimitStrategy { queue, reject }

Parameters

ParameterTypeDefaultDescription
maxCallsintrequiredMaximum allowed executions per window.
windowDurationrequiredSliding time window.
strategyRateLimitStrategyqueuequeue waits for the next slot; reject throws RateLimitException.

Examples

Basic example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var calls = 0;
final limitedApi = Func<int>(() async => ++calls).rateLimit(
  maxCalls: 2,
  window: Duration(seconds: 1),
  strategy: RateLimitStrategy.tokenBucket,
);

await limitedApi();
await limitedApi();
final third = limitedApi(); // queued until the window refreshes
await third;
// calls == 3
print(calls);

Real-world example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
final sendEmail = Func1<Email, void>((email) async {
  await mailer.send(email);
}).rateLimit(
  maxCalls: 10,
  window: Duration(minutes: 1),
  strategy: RateLimitStrategy.slidingWindow,
);

void main() async {
  await sendEmail(Email());
}

Best practices

  • Choose reject for user-facing operations that should fail fast.
  • Choose queue for background tasks where latency is acceptable.
  • Set maxCalls slightly below the actual provider limit to leave headroom.

Common pitfalls

  • Bursts at window boundaries: Sliding windows smooth bursts better than fixed windows; funx uses a sliding window.
  • Queue growth: With queue, a sustained overload can create a long backlog.