rate_limits
Overview
The rate_limits table tracks rate limit state for each user and action type. It records the count of actions within the current time window. Combined with rate_limit_config, this implements a sliding-window rate limiting system that prevents abuse while remaining invisible to normal users.
Relevant Invariants
- Invariant #11: "System Resists Optimization" -- Rate limiting prevents automated abuse
- Invariant #20: "Misuse Should Break the System" -- Rate limits make misuse patterns feel awkward
Schema
-- From 20260205_rate_limiting_fixed.sql
CREATE TABLE rate_limits (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
action_type TEXT NOT NULL,
window_start TIMESTAMPTZ DEFAULT NOW(),
action_count INTEGER DEFAULT 1,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, action_type)
);
Columns
| Column | Type | Nullable | Default | Description |
|---|---|---|---|---|
id | uuid | No | gen_random_uuid() | Primary key |
user_id | uuid | No | -- | User being rate limited |
action_type | text | No | -- | Action identifier (e.g., 'create_post') |
window_start | timestamptz | No | NOW() | Start of current rate window |
action_count | integer | No | 1 | Actions taken in current window |
created_at | timestamptz | No | NOW() | Row creation timestamp |
RLS Policies
-- SELECT: Users can view their own rate limits
CREATE POLICY "Users can view own rate limits"
ON rate_limits FOR SELECT
USING (auth.uid() = user_id);
Helper Functions
-- Check if user is within rate limit
check_rate_limit(p_user_id UUID, p_action TEXT) RETURNS BOOLEAN
-- Record an action for rate limiting
record_rate_limit_action(p_user_id UUID, p_action TEXT) RETURNS VOID
-- Combined check + record
enforce_rate_limit(p_user_id UUID, p_action TEXT) RETURNS BOOLEAN
Related
- rate_limit_config -- Configuration for each action type
- profiles -- Rate-limited user
Last updated: 2026-02-07