Skip to main content

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

ColumnTypeNullableDefaultDescription
iduuidNogen_random_uuid()Primary key
user_iduuidNo--User being rate limited
action_typetextNo--Action identifier (e.g., 'create_post')
window_starttimestamptzNoNOW()Start of current rate window
action_countintegerNo1Actions taken in current window
created_attimestamptzNoNOW()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

Last updated: 2026-02-07