Skip to content

Commit 77cfb07

Browse files
committed
Add TTL expiration to rate limit shards
1 parent bb08dd8 commit 77cfb07

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

src/lib/rate-limit.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getDocsFromServer,
55
increment,
66
setDoc,
7+
Timestamp,
78
} from 'firebase/firestore';
89
import { getDb } from './db';
910

@@ -15,6 +16,7 @@ interface RateLimitOptions {
1516
interface RateLimitDocument {
1617
count: number;
1718
windowStart: number;
19+
expiresAt?: Timestamp;
1820
}
1921

2022
export interface RateLimitState {
@@ -27,6 +29,9 @@ export interface RateLimitState {
2729
const DEFAULT_WINDOW_MS = 60_000;
2830
const DEFAULT_MAX_REQUESTS = 30;
2931
const SHARD_COUNT = 20;
32+
// Documents are cleaned up via Firestore TTL configured on the `expiresAt` field.
33+
// Keeping a modest retention allows slow TTL sweeps without impacting active windows.
34+
const RETENTION_WINDOWS = 24; // number of windows to keep for TTL cleanup
3035

3136
export async function enforceRateLimit(
3237
key: string,
@@ -38,10 +43,11 @@ export async function enforceRateLimit(
3843
const windowRef = collection(db, 'rateLimits', `${key}:${windowStart}`, 'shards');
3944
const shardId = Math.floor(Math.random() * SHARD_COUNT).toString();
4045
const shardRef = doc(windowRef, shardId);
46+
const expiresAt = Timestamp.fromMillis(windowStart + windowMs * RETENTION_WINDOWS);
4147

4248
await setDoc(
4349
shardRef,
44-
{ count: increment(1), windowStart },
50+
{ count: increment(1), windowStart, expiresAt },
4551
{ merge: true },
4652
);
4753

0 commit comments

Comments
 (0)