Every application accumulates temporary data — session tokens, verification codes, promotional offers, draft content. Without automatic cleanup, these records pile up, consume storage, and slow down queries. Manual cleanup scripts are fragile and easy to forget.
Centrali's Record TTL (Time-To-Live) solves this by letting you set an expiration time on any record. Once expired, records are automatically excluded from query results and permanently deleted by a background sweep. No cron jobs. No manual intervention.
New to TTL as a concept? Start with What Is Record TTL? Database Time-to-Live Explained — definition, when to use it, and how database TTL differs from DNS TTL. This post is the hands-on follow-up.
What is Record TTL?
Record TTL is a built-in data expiration feature that works at the record level:
- Set a TTL — specify
ttlSeconds(duration) orexpiresAt(timestamp) when creating or updating a record - Record gets an
expiresAttimestamp — calculated automatically from the TTL - Expired records disappear from queries — read-time filtering excludes them instantly
- Background sweep deletes permanently — runs every 2 minutes, publishes
record.expiredevents
You can also set a default TTL on a structure, so every new record in that structure automatically expires after the configured duration.
Use Case 1: Session Tokens
Session management is the most common TTL use case. Set a 24-hour default on your Sessions structure, and every session record expires automatically.
Set Up the Structure
import { CentraliSDK } from '@centrali-io/centrali-sdk';const centrali = new CentraliSDK({workspaceId: 'my-workspace',clientId: process.env.CENTRALI_CLIENT_ID,clientSecret: process.env.CENTRALI_CLIENT_SECRET,});// Set 24-hour default TTL on Sessionsawait centrali.structures.update('sessions-structure-id', {defaultTtlSeconds: 86400, // 24 hours});
Create a Session
const session = await centrali.createRecord('Sessions', {userId: 'user-123',deviceInfo: 'Chrome on macOS',lastActivity: new Date().toISOString(),});console.log(session.data.expiresAt);// → "2026-02-28T10:00:00Z" (24 hours from now)
Sliding Expiration
Reset the TTL on each user action to keep active sessions alive:
// On every authenticated requestawait centrali.updateRecord('Sessions', sessionId, {lastActivity: new Date().toISOString(),}, { ttlSeconds: 86400 }); // Reset to 24 hours
Inactive sessions expire and are cleaned up automatically. Active sessions keep extending.
Use Case 2: Promotional Codes
Time-limited promotions need precise expiration. Use expiresAt for business deadlines and ttlSeconds for short-lived flash coupons.
Create a Promo with a Deadline
// Summer sale ends September 1stconst promo = await centrali.createRecord('Promotions', {code: 'SUMMER2026',discountPercent: 20,minOrderTotal: 50,}, { expiresAt: '2026-09-01T00:00:00Z' });
Create a Flash Coupon
// One-hour flash dealconst flash = await centrali.createRecord('Promotions', {code: 'FLASH50',discountPercent: 50,}, { ttlSeconds: 3600 });
Validate at Checkout
No special filtering needed. Expired promos are automatically excluded from queries:
const result = await centrali.queryRecords('Promotions', {'data.code': customerCode,});if (result.data.length === 0) {throw new Error('Invalid or expired promo code');}// If we get here, the promo is valid and not expiredconst discount = result.data[0].data.discountPercent;
Use Case 3: Draft Content
Auto-expire abandoned drafts after 30 days. When a draft is published, remove the TTL so it lives permanently.
Configure the Structure
// Set 30-day default TTL on BlogPost structureawait centrali.structures.update('blogpost-structure-id', {defaultTtlSeconds: 2592000, // 30 days});
Create a Draft
New drafts inherit the 30-day TTL automatically:
const draft = await centrali.createRecord('BlogPost', {title: 'Work in Progress',content: 'This is a rough draft...',status: 'draft',});console.log(draft.data.expiresAt); // 30 days from now
Publish and Clear TTL
await centrali.updateRecord('BlogPost', draft.id, {status: 'published',publishedAt: new Date().toISOString(),}, { clearTtl: true }); // Make permanent
The published post now has expiresAt: null and will never be automatically deleted.
Using the REST API
All TTL operations are available via query parameters on the REST API.
Create with TTL
curl -X POST "https://api.centrali.io/data/workspace/acme/api/v1/records?ttlSeconds=3600" \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{"structureId": "str_sessions","data": {"userId": "user-123","token": "abc-xyz"}}'
Remove TTL
curl -X PATCH "https://api.centrali.io/data/workspace/acme/api/v1/records/rec_xyz789?clearTtl=true" \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{ "data": {} }'
Set Structure Default
curl -X PUT "https://api.centrali.io/data/workspace/acme/api/v1/structures/str_sessions" \-H "Authorization: Bearer YOUR_API_KEY" \-H "Content-Type: application/json" \-d '{ "defaultTtlSeconds": 86400 }'
What Happens Under the Hood
When you set a TTL on a record, three things happen:
- Immediate: The record gets an
expiresAttimestamp in the database - On every query: A read-time filter (
WHERE expiresAt IS NULL OR expiresAt > NOW()) excludes expired records from all API responses — lists, gets, counts, and search results - Every 2 minutes: A background sweep acquires a distributed Redis lock, finds expired records in batches, runs each through the full delete pipeline (storage cleanup, search index removal), and publishes a
record.expiredNATS event for each
The record.expired event lets you trigger downstream cleanup — revoke OAuth tokens, send expiration notifications, or update analytics.
Get Started
Install the SDK and start using TTL in three lines:
npm install @centrali-io/centrali-sdk
import { CentraliSDK } from '@centrali-io/centrali-sdk';const centrali = new CentraliSDK({ workspaceId: 'my-workspace', clientId: 'YOUR_CLIENT_ID', clientSecret: 'YOUR_CLIENT_SECRET' });// Create a record that expires in 1 hourawait centrali.createRecord('Sessions', { userId: 'user-123' }, { ttlSeconds: 3600 });
Check the Record TTL documentation for the full reference, including TTL priority rules, best practices, and more use cases.