Skip to Content
Internal docs are powered by Nextra Docs Theme.
ProjectsTurbopuffer to Postgres exit plan

Turbopuffer to Postgres exit plan

Date: September 7, 2026

Why

Turbopuffer is now a meaningful usage-based vendor cost. The September 1 invoice for August was $498.75, driven mostly by writes ($335.90), then storage ($86.93), then Voyage embeddings ($70.12). Query cost was negligible.

The current product can survive without Turbopuffer because conversation search already falls back to Postgres full-text search over api2.conversation_part_chunks.

Immediate change

API2 now requires TURBOPUFFER_ENABLED=true in addition to the Turbopuffer API key and endpoint settings. The default is false, so production deploys fall back to Postgres full-text search and skip Turbopuffer indexing/topic jobs unless we explicitly opt back in.

After deploy, remove TURBOPUFFER_ENABLED or set it to false in all environments, then confirm no Turbopuffer writes/embeddings are recorded for 24 hours before canceling the Turbopuffer account.

Replacement scope

  1. Keep conversation_part_chunks as the source of truth for transcript/message body retrieval.
  2. Add the missing Postgres indexes needed for cheap full-text search at customer scale, using generated tsvector or expression indexes on chunk content plus tenant/date filters.
  3. Replace conversation topic and customer issue nearest-neighbor matching with Postgres-backed logic:
    • use existing customer_issue_id/field mapping where available;
    • use deterministic text search as the first fallback;
    • only add pgvector embeddings if quality materially regresses without semantic matching.
  4. Remove scheduled Turbopuffer indexing and backfill maintenance tasks after the fallback has been production-dark for a week.
  5. Delete Turbopuffer namespaces and cancel the account only after a successful dark period, because canceling schedules deletion of all namespaces/API keys.

Watch points

  • Search quality may get more lexical until we add pgvector or better deterministic matching.
  • Full-text search has AND semantics through plainto_tsquery('simple', query), so broad natural-language searches may need query rewriting or multiple shorter searches.
  • If customer issue assignment quality drops, start with the field-mapping path before reintroducing paid vector search.
Last updated on