cost per active user hit $1.90 on a $9 plan after adding pgvector search Unit Economics
Note-taking tool for researchers, $9/mo flat, 640 monthly actives. Infra was $310/mo and comfortable. Then I shipped semantic search: chunk every note, embed with a hosted embedding model, store in Postgres with pgvector, HNSW index.
Infra is now $1,216/mo. Rough split:
- embeddings API: $402
- Postgres compute: $611 (was $180)
- storage + everything else: $203
That is $1.90 per active user against $9 of revenue, before payment fees, and my heaviest 5% of users are obviously much worse than the average. Gross margin went from ~87% to ~79% overall but the tail is what worries me.
The embedding cost is because I re-embed a note on every save. People save constantly. A single note gets re-embedded 30 times in an afternoon while someone edits it.
The Postgres number I genuinely do not understand. The instance was fine before and the query volume did not change much.
@back_of_envelope · 2mo ago · 3 replies
Re-embedding on every save is the whole $402 and it's the easiest thing on your list to fix.
Chunk first, hash each chunk, store the hash next to the vector. On save, re-chunk, and only send chunks whose hash changed. Someone editing paragraph 4 of an 11-paragraph note re-embeds one chunk, not eleven. Our re-embed volume dropped 94% and the quality is identical because the unchanged text produces the identical vector anyway.
Second, debounce. There is no reason to embed on keystroke-save. Queue it, coalesce, run 30 seconds after the last edit. Combined with hashing that took us from ~180k embed calls a day to about 6k.
Third, check whether your embedding model supports shortened output dimensions. If it does, going from 1536 to 768 halves your index size and your index build time with a small retrieval quality hit that is usually invisible for a notes product. Measure it on your own data before you commit, obviously.
Reply
Report
@pgpolicy_nadia · 2mo ago
Chunk hashing is obvious in hindsight and I feel silly. Question: when a chunk boundary shifts because someone inserted a sentence early in the note, does that not invalidate every downstream chunk anyway?
Reply
Report
@packlist_pen · 2mo ago
It does with naive fixed-size chunking, which is why content-defined boundaries help - split on headings or paragraphs rather than every N tokens. Then an insert in paragraph 2 only dirties paragraph 2. Worst case you fall back to re-embedding a section, not the document.
Reply
Report