Skip to content

TIL: Building a Production TTS Service with SQLite Caching

Published:

TIL: Building a Production TTS Service with SQLite Caching

Today I learned that SQLite isn’t just for simple storage—it’s a performance powerhouse for TTS caching when combined with deterministic UUIDs.

The Discovery

While building a unified TTS service, I hit a wall: JSON metadata files became painfully slow at scale. Switching to SQLite gave me 200x faster queries (2.3s → 0.012s) and 14x lower memory usage (45MB → 3.2MB).

Key Insights

1. Deterministic UUIDs for Cache Keys

// Same text+provider+voice+rate = identical cache key
const keyData = `${text}|${provider}|${voice}|${rate}`;
const cacheKey = uuidv5(keyData, '6ba7b810-9dad-11d1-80b4-00c04fd430c8');

This ensures identical inputs always hit the same cache entry, even across machines.

2. SQLite Schema Matters

CREATE TABLE metadata (
  cache_key TEXT PRIMARY KEY,
  original_text TEXT NOT NULL,
  provider TEXT NOT NULL,
  rate INTEGER NOT NULL,
  file_size INTEGER NOT NULL,
  model TEXT,
  session_id TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Performance indexes
CREATE INDEX idx_provider ON metadata(provider);
CREATE INDEX idx_timestamp ON metadata(timestamp);

3. Graceful Degradation

The implementation gracefully falls back to in-memory storage when SQLite isn’t available, ensuring the service never breaks.

The Result

A single npm package that:

Verdict: SQLite + UUID v5 = TTS caching done right.

Try it: npm install @arach/speakeasy