Cache & Queue
Two simpler but essential modules for production applications. Cache gives you sub-millisecond key-value storage at the edge. Queue lets you offload work to background jobs with automatic retries.
Globally replicated key-value cache with TTL support, atomic counters, and bulk operations. Data is replicated globally for low-latency reads from any edge location.
What you can build with Cache
Section titled “What you can build with Cache”- Session storage — Store user sessions with automatic expiry
- Rate limiting — Atomic counters to track request rates per user/IP
- Feature flags — Store and update feature flags without redeploying
- Computed results — Cache expensive database queries or API responses
- View counters — Atomic increment for page views, likes, votes
- Shopping carts — Temporary cart data with TTL expiry
Basic operations
Section titled “Basic operations”// Set a value (with optional TTL in seconds)await sdk.cache.set('user:123', { name: 'Jane', plan: 'pro' }, { ttl: 3600 })
// Set with metadataawait sdk.cache.set('session:abc', sessionData, { ttl: 1800, metadata: { userId: '123', device: 'mobile' },})
// Get a value (null if not found or expired)const user = await sdk.cache.get('user:123')
// Check existenceconst exists = await sdk.cache.has('user:123')
// Deleteawait sdk.cache.delete('user:123')// Set with TTLerr = client.Cache.Set(ctx, "user:123", userData, 3600)
// Getvar user Userfound, err := client.Cache.Get(ctx, "user:123", &user)
// Check existenceexists, err := client.Cache.Has(ctx, "user:123")
// Deleteerr = client.Cache.Delete(ctx, "user:123")# Set with TTLawait client.cache.set("user:123", user_data, ttl=3600)
# Getuser = await client.cache.get("user:123")
# Check existenceexists = await client.cache.has("user:123")
# Deleteawait client.cache.delete("user:123")Bulk operations
Section titled “Bulk operations”Efficiently get, set, or delete multiple keys in a single round-trip:
// Get manyconst values = await sdk.cache.getMany(['user:1', 'user:2', 'user:3'])// { 'user:1': {...}, 'user:2': {...}, 'user:3': null }
// Set manyawait sdk.cache.setMany({ 'user:1': { name: 'Alice' }, 'user:2': { name: 'Bob' }, 'user:3': { name: 'Carol' },}, { ttl: 3600 })
// Delete manyawait sdk.cache.deleteMany(['user:1', 'user:2', 'user:3'])List keys
Section titled “List keys”// List all keys with a prefixconst keys = await sdk.cache.keys({ prefix: 'session:' })// ['session:abc', 'session:def', 'session:ghi']
// List with metadataconst entries = await sdk.cache.list({ prefix: 'session:' })// [{ key: 'session:abc', metadata: { userId: '123' } }, ...]Atomic counters
Section titled “Atomic counters”Increment or decrement values atomically. Perfect for rate limiting, view counts, and voting:
// Increment (creates key with value 1 if it doesn't exist)const newCount = await sdk.cache.increment('views:post-123')// 1, 2, 3, ...
// Increment by a specific amountconst newCount = await sdk.cache.increment('views:post-123', 5)
// Use for rate limitingasync function checkRateLimit(userId: string, limit: number) { const key = `ratelimit:${userId}:${Math.floor(Date.now() / 60000)}` const count = await sdk.cache.increment(key)
if (count === 1) { // First request in this minute window -- set TTL await sdk.cache.expire(key, 60) }
return count <= limit}Set expiry on existing key
Section titled “Set expiry on existing key”await sdk.cache.expire('session:abc', 1800) // 30 minutes from nowFlush all cache
Section titled “Flush all cache”await sdk.cache.flush() // Delete everything -- use with cautionComplete example: session store
Section titled “Complete example: session store”import { AerostackClient } from '@aerostack/sdk'
const { sdk } = new AerostackClient({ projectId, apiKey })
async function createSession(userId: string, device: string) { const sessionId = crypto.randomUUID()
await sdk.cache.set(`session:${sessionId}`, { userId, device, createdAt: Date.now(), lastActive: Date.now(), }, { ttl: 86400, // 24 hours metadata: { userId, device }, })
return sessionId}
async function getSession(sessionId: string) { const session = await sdk.cache.get(`session:${sessionId}`) if (!session) return null
// Refresh TTL on access await sdk.cache.set(`session:${sessionId}`, { ...session, lastActive: Date.now(), }, { ttl: 86400 })
return session}
async function destroySession(sessionId: string) { await sdk.cache.delete(`session:${sessionId}`)}
async function getUserSessions(userId: string) { const entries = await sdk.cache.list({ prefix: 'session:' }) return entries.filter(e => e.metadata?.userId === userId)}Complete example: feature flags
Section titled “Complete example: feature flags”async function setFlag(name: string, value: boolean, metadata?: Record<string, any>) { await sdk.cache.set(`flag:${name}`, { enabled: value, ...metadata })}
async function getFlag(name: string): Promise<boolean> { const flag = await sdk.cache.get(`flag:${name}`) return flag?.enabled ?? false}
async function getAllFlags() { const keys = await sdk.cache.keys({ prefix: 'flag:' }) const values = await sdk.cache.getMany(keys) return Object.fromEntries( keys.map(k => [k.replace('flag:', ''), values[k]?.enabled ?? false]) )}
// Usageawait setFlag('new-checkout', true)await setFlag('dark-mode', true, { rollout: 50 })
if (await getFlag('new-checkout')) { // Show new checkout flow}Cache API reference
Section titled “Cache API reference”| Method | Signature | Returns |
|---|---|---|
sdk.cache.get | (key: string) => Promise<T | null> | Cached value or null |
sdk.cache.set | (key: string, value: any, opts?: { ttl?, metadata? }) => Promise<void> | Nothing |
sdk.cache.delete | (key: string) => Promise<void> | Nothing |
sdk.cache.has | (key: string) => Promise<boolean> | Boolean |
sdk.cache.getMany | (keys: string[]) => Promise<Record<string, T>> | Map of key to value |
sdk.cache.setMany | (entries: Record<string, any>, opts?) => Promise<void> | Nothing |
sdk.cache.deleteMany | (keys: string[]) => Promise<void> | Nothing |
sdk.cache.keys | (opts?: { prefix? }) => Promise<string[]> | Array of keys |
sdk.cache.list | (opts?: { prefix? }) => Promise<{ key, metadata }[]> | Keys with metadata |
sdk.cache.increment | (key: string, amount?: number) => Promise<number> | New value |
sdk.cache.expire | (key: string, ttl: number) => Promise<void> | Nothing |
sdk.cache.flush | () => Promise<void> | Nothing |
Background job processing with configurable retries, delays, and status tracking. Jobs are durably stored and guaranteed to execute at least once.
What you can build with Queue
Section titled “What you can build with Queue”- Email notifications — Send welcome emails, password resets, order confirmations
- PDF generation — Generate invoices, reports, or certificates in the background
- Batch imports — Process CSV uploads row by row without blocking the request
- Image processing — Resize, crop, or optimize uploaded images
- Webhook delivery — Retry failed webhook deliveries with exponential backoff
- Scheduled tasks — Delay job execution for reminders, follow-ups, or scheduled reports
- Data sync — Sync data between Aerostack and external systems
Enqueue a job
Section titled “Enqueue a job”// Simple jobawait sdk.queue.enqueue('send-welcome-email', { userId: 'user-123', email: 'jane@example.com', name: 'Jane',})
// Job with optionsawait sdk.queue.enqueue('generate-report', { reportType: 'monthly', month: '2026-03', userId: 'user-123',}, { delaySeconds: 60, // Wait 1 minute before processing maxRetries: 5, // Retry up to 5 times on failure})err = client.Queue.Send(ctx, "send-welcome-email", payload, aerostack.QueueOptions{ DelaySeconds: 0, MaxRetries: 3,})await client.queue.send( "send-welcome-email", {"userId": "user-123", "email": "jane@example.com"}, delay_seconds=0, max_retries=3)Check job status
Section titled “Check job status”const job = await sdk.queue.getJob(jobId)// { id, type, status, payload, attempts, maxRetries, createdAt, scheduledAt, completedAt }| Status | Description |
|---|---|
pending | Waiting to be processed (or delayed) |
processing | Currently being executed |
completed | Successfully finished |
failed | All retries exhausted |
cancelled | Manually cancelled |
List jobs
Section titled “List jobs”const jobs = await sdk.queue.listJobs({ type: 'send-welcome-email', // optional filter status: 'pending', // optional filter limit: 50,})Cancel a job
Section titled “Cancel a job”await sdk.queue.cancelJob(jobId)Complete example: email notification pipeline
Section titled “Complete example: email notification pipeline”import { AerostackClient } from '@aerostack/sdk'
const { sdk } = new AerostackClient({ projectId, apiKey })
// Enqueue from your API handlerasync function onUserSignup(user: { id: string, email: string, name: string }) { // Send welcome email immediately await sdk.queue.enqueue('send-email', { template: 'welcome', to: user.email, data: { name: user.name }, })
// Send onboarding tip after 24 hours await sdk.queue.enqueue('send-email', { template: 'onboarding-tip-1', to: user.email, data: { name: user.name }, }, { delaySeconds: 86400 })
// Send follow-up after 3 days await sdk.queue.enqueue('send-email', { template: 'onboarding-tip-2', to: user.email, data: { name: user.name }, }, { delaySeconds: 259200 })}
// Process jobs in your workerasync function processEmailJob(job: { type: string, payload: any }) { const { template, to, data } = job.payload
// Send via your email provider await sendEmail({ template, to, data })
// Log in database await sdk.db.query( 'INSERT INTO email_log (id, template, recipient, sent_at) VALUES (?, ?, ?, ?)', [crypto.randomUUID(), template, to, Date.now()] )}Complete example: batch CSV import
Section titled “Complete example: batch CSV import”async function importCSV(userId: string, csvContent: string) { const rows = parseCSV(csvContent)
// Enqueue each row as a separate job (can process in parallel) for (const row of rows) { await sdk.queue.enqueue('import-row', { userId, data: row, }, { maxRetries: 3 }) }
// Track the import await sdk.db.query( 'INSERT INTO imports (id, user_id, total_rows, status, created_at) VALUES (?, ?, ?, ?, ?)', [crypto.randomUUID(), userId, rows.length, 'processing', Date.now()] )}Queue API reference
Section titled “Queue API reference”| Method | Signature | Returns |
|---|---|---|
sdk.queue.enqueue | (type: string, payload: any, opts?: { delaySeconds?, maxRetries? }) => Promise<{ jobId: string }> | Job ID |
sdk.queue.getJob | (jobId: string) => Promise<Job> | Job details |
sdk.queue.listJobs | (opts?: { type?, status?, limit? }) => Promise<Job[]> | Array of jobs |
sdk.queue.cancelJob | (jobId: string) => Promise<void> | Nothing |