Rate limiting database schema
A rate limiting schema with named quotas, per-key buckets that track the current window, and an audit log for billable usage. Pairs with a Redis fast path; this is the durable store.
Database schema previewRate limiting database schema
Recreate this in Raltey
Copy this prompt
Paste this into Raltey's AI agent to generate the same diagram, then tweak it on the canvas.
Prompt
Design a PostgreSQL database schema for: Rate limiting database schema. A rate limiting schema with named quotas, per-key buckets that track the current window, and an audit log for billable usage. Pairs with a Redis fast path; this is the durable store. Include these tables: quota, rate_bucket, rate_audit. Use proper primary keys, foreign keys, and indexes. Export SQL DDL for PostgreSQL.
Context
- - Real-time decisions live in Redis; this DB is the durable record.
- - Buckets are upserted at the end of each window.
- - Audit log captures denied requests for support and billing.
Patterns
- - Sliding-window counters keyed by (key, quota, window_started).
- - Redis is the hot path; Postgres is the recoverable source of truth.
- - Audit log keeps only denied or notable events to bound size.
Tables
The schema, table by table
quota
DBML - quota
Table quota {
id uuid pk
name text unique not null // api:reads, ai:generations
window_sec int not null
max_count int not null
}rate_bucket
Per-key counter for the current window.
DBML - rate_bucket
Table rate_bucket {
key text not null // user:123, ip:1.2.3.4
quota_id uuid [ref: > quota.id]
window_started timestamptz not null
count int not null default 0
pk (key, quota_id, window_started)
}rate_audit
Append-only log of denied or notable requests.
DBML - rate_audit
Table rate_audit {
id uuid pk
key text not null
quota_id uuid [ref: > quota.id]
occurred_at timestamptz default `now()`
denied boolean not null
metadata jsonb
}Relationships
| From | To | Type |
|---|---|---|
| quota | rate_bucket | 1:N |
| quota | rate_audit | 1:N |
Notes from the field
- Drop rate_bucket rows older than the longest quota window via a cron.
- Index rate_audit(key, occurred_at DESC) for support lookups.
- For per-user pricing buckets, sum count grouped by user across a billing period.
Frequently asked
Why store rate-limit state in Postgres at all?
For billing, audit, and recovery. Redis is volatile; this table survives a Redis outage and produces the monthly usage report.
How do I support sliding windows?
Keep multiple rate_bucket rows per key (overlapping windows). At decision time, sum the relevant windows. For most apps, fixed windows are enough.
More templates
FlowchartSaaS onboarding email flowFlowchartCustomer support runbook flowFlowchartPayment webhook retry and error flowFlowchartGitHub PR review and merge flowFlowchartLogin with magic link flowArchitectureThree-tier SaaS architecture on AWSArchitectureMicroservices architecture on KubernetesArchitectureReal-time data pipeline on GCP
Open this template in Raltey
Edit it on the canvas, ask the AI agent to extend it, then share or export.
Start for free