-- Add rate limiting columns to api_keys table ALTER TABLE api_keys ADD COLUMN IF NOT EXISTS rate_limit_per_minute INT DEFAULT 60, ADD COLUMN IF NOT EXISTS rate_limit_per_hour INT DEFAULT 1000; -- Create rate_limit_state table to track per-key usage windows CREATE TABLE IF NOT EXISTS rate_limit_state ( id SERIAL PRIMARY KEY, api_key_id UUID NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE, window_start TIMESTAMPTZ NOT NULL, window_type VARCHAR(10) NOT NULL, -- 'minute' or 'hour' request_count INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (api_key_id, window_start, window_type) ); -- Index for efficient lookups by api_key_id and window CREATE INDEX IF NOT EXISTS idx_rate_limit_state_lookup ON rate_limit_state(api_key_id, window_type, window_start DESC); -- Index for cleanup of old entries CREATE INDEX IF NOT EXISTS idx_rate_limit_state_cleanup ON rate_limit_state(window_start); COMMENT ON TABLE rate_limit_state IS 'Tracks rate limit usage per API key per time window'; COMMENT ON COLUMN rate_limit_state.window_start IS 'Start of the time window (truncated to minute or hour)'; COMMENT ON COLUMN rate_limit_state.window_type IS 'Type of window: minute or hour'; COMMENT ON COLUMN rate_limit_state.request_count IS 'Number of requests in this window'; COMMENT ON COLUMN api_keys.rate_limit_per_minute IS 'Maximum requests allowed per minute (default: 60)'; COMMENT ON COLUMN api_keys.rate_limit_per_hour IS 'Maximum requests allowed per hour (default: 1000)';