Usage Examples
Real-world examples of using pg_ttl_index in various scenarios.
Session Management
Web Application Sessions
-- Create sessions table
CREATE TABLE user_sessions (
session_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id INTEGER NOT NULL,
ip_address INET,
user_agent TEXT,
session_data JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_activity TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Index for user lookups
CREATE INDEX idx_user_sessions_user_id ON user_sessions(user_id);
-- TTL: expire sessions after 30 minutes of inactivity
SELECT ttl_create_index('user_sessions', 'last_activity', 1800);
API Token Expiration
-- API tokens with expiration
CREATE TABLE api_tokens (
token_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id INTEGER NOT NULL,
token_hash TEXT NOT NULL,
scopes TEXT[],
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
-- TTL: clean up immediately when expired
SELECT ttl_create_index('api_tokens', 'expires_at', 0);
Log Management
Application Logs
-- Centralized application logs
CREATE TABLE app_logs (
id BIGSERIAL PRIMARY KEY,
service_name VARCHAR(100) NOT NULL,
level VARCHAR(10) NOT NULL,
message TEXT NOT NULL,
metadata JSONB,
logged_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Partition by service for better performance
CREATE INDEX idx_app_logs_service ON app_logs(service_name);
-- TTL: keep logs for 7 days
SELECT ttl_create_index('app_logs', 'logged_at', 604800, 50000);
Audit Trail
-- Compliance audit log
CREATE TABLE audit_trail (
id BIGSERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
action VARCHAR(50) NOT NULL,
resource_type VARCHAR(50),
resource_id INTEGER,
details JSONB,
ip_address INET,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TTL: retain for 90 days (compliance requirement)
SELECT ttl_create_index('audit_trail', 'created_at', 7776000, 25000);
Cache Management
Application Cache
-- Simple key-value cache
CREATE TABLE cache_entries (
cache_key VARCHAR(255) PRIMARY KEY,
cache_value TEXT NOT NULL,
tags TEXT[],
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
-- TTL: respect expires_at column
SELECT ttl_create_index('cache_entries', 'expires_at', 0, 10000);
Query Result Cache
-- Cache expensive query results
CREATE TABLE query_cache (
query_hash VARCHAR(64) PRIMARY KEY,
query_sql TEXT NOT NULL,
result_data JSONB NOT NULL,
cached_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TTL: invalidate cache after 1 hour
SELECT ttl_create_index('query_cache', 'cached_at', 3600);
Analytics & Metrics
Event Tracking
-- User events for analytics
CREATE TABLE user_events (
id BIGSERIAL PRIMARY KEY,
user_id INTEGER,
event_type VARCHAR(50) NOT NULL,
properties JSONB,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Partition by date for better performance
CREATE INDEX idx_user_events_timestamp ON user_events(timestamp);
-- TTL: raw events kept for 24 hours
SELECT ttl_create_index('user_events', 'timestamp', 86400, 100000);
Time-Series Metrics
-- Metrics collected every second
CREATE TABLE system_metrics (
id BIGSERIAL PRIMARY KEY,
metric_name VARCHAR(100) NOT NULL,
metric_value NUMERIC NOT NULL,
tags JSONB,
collected_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TTL: keep raw metrics for 6 hours
SELECT ttl_create_index('system_metrics', 'collected_at', 21600, 100000);
E-Commerce
Shopping Carts
-- Abandoned cart management
CREATE TABLE shopping_carts (
cart_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id INTEGER,
session_id TEXT,
items JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TTL: abandon carts after 24 hours of inactivity
SELECT ttl_create_index('shopping_carts', 'updated_at', 86400);
Price History
-- Track price changes over time
CREATE TABLE price_history (
id BIGSERIAL PRIMARY KEY,
product_id INTEGER NOT NULL,
price NUMERIC(10, 2) NOT NULL,
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- TTL: keep price history for 30 days
SELECT ttl_create_index('price_history', 'recorded_at', 2592000, 50000);
Job Queues
Background Jobs
-- Job queue with automatic cleanup
CREATE TABLE background_jobs (
job_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
job_type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
-- TTL: clean up completed jobs after 7 days
SELECT ttl_create_index('background_jobs', 'completed_at', 604800);
Notifications
User Notifications
-- In-app notifications
CREATE TABLE notifications (
id BIGSERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
message TEXT NOT NULL,
read BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_notifications_user_id ON notifications(user_id);
-- TTL: delete read notifications after 30 days
SELECT ttl_create_index('notifications', 'created_at', 2592000);
Rate Limiting
API Rate Limit Tracking
-- Track API requests for rate limiting
CREATE TABLE api_rate_limits (
id BIGSERIAL PRIMARY KEY,
api_key VARCHAR(64) NOT NULL,
endpoint VARCHAR(255) NOT NULL,
request_count INTEGER NOT NULL DEFAULT 1,
window_start TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_rate_limits ON api_rate_limits(api_key, endpoint, window_start);
-- TTL: sliding window of 1 hour
SELECT ttl_create_index('api_rate_limits', 'window_start', 3600, 50000);
Multi-Tenant Setup
-- Different TTL per tenant
CREATE TABLE tenant_data (
id BIGSERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL,
data_type VARCHAR(50) NOT NULL,
data JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Tenant A: 7 days retention
CREATE VIEW tenant_a_data AS
SELECT * FROM tenant_data WHERE tenant_id = 1;
SELECT ttl_create_index('tenant_data', 'created_at', 604800);
-- Note: Use partitioning for true per-tenant TTL
See Also
- Best Practices - Optimization tips
- Monitoring - Track cleanup effectiveness
- API Reference - Function documentation