HomeServicesPortfolioAboutContactBlogCareers
Book a call
Retail

The Async Re-Embed Pipeline: Keeping a Vector Index Fresh Without Blocking Writes

September 2026 · ISTRALLEN Team

The problem with re-embedding on every write

A supplier feed touches product rows thousands of times a week. If every write triggers a synchronous re-embed, you've put an external API call on the critical path of catalogue updates — the feed slows down or stalls, and now your search infrastructure is a bottleneck on your merchandising. An async re-embedding pipeline moves that work off the write path.

The trigger-and-queue pattern

  • A write fires a database trigger.
  • The trigger inspects which columns changed. A semantic-field change — title, description, category, key attributes — enqueues a re-embed job. A price or stock change updates the vector record's metadata and stops there, with no embedding call.
  • A worker drains the queue, calls the embedding model for each queued product, and writes the new vector.

On our semantic search project this is exactly the shape — a trigger-and-queue keyed to semantic-field changes only.

The filter is what keeps cost sane

A catalogue touched thousands of times a week by price ticks would otherwise generate thousands of pointless embedding calls — the price didn't change what the text means, so re-embedding on it is pure wasted spend. Filtering at the trigger level, before anything is queued, is the difference between a manageable bill and a runaway one.

Backpressure and ordering

If the embedding API is slow or rate-limited, the queue absorbs it — the feed keeps running while the worker catches up. Process jobs per product in order so the latest edit wins; a stale re-embed overwriting a newer one is a subtle bug worth designing out.

The full re-index is separate

Re-embedding everything is a manually-run job for a model swap or a change to the composed-field recipe — rare and deliberate. The async pipeline handles the continuous churn; the full re-index handles the occasional structural change.

When to move to change-data-capture

If re-embed volume outgrows a single worker, or a second system needs the same change events, change-data-capture tooling gives decoupled, replayable streams to multiple consumers. A single-instance Postgres with filtered triggers doesn't need it — that's the escalation, not the starting point.

What the trigger inspects, concretely

The trigger fires on any row update. It compares the old and new values of the semantic columns — title, description, category, the attribute set. If any of those changed, it enqueues a job carrying just the product ID. If only price, stock, or inventory columns changed, it updates the vector record's metadata in place and returns without queuing anything. That branch — metadata update versus re-embed — is the whole cost-control mechanism, and it lives in a few lines of trigger logic.

Idempotent workers

The worker keys on the product ID and always re-embeds from the current row, not from a diff. So a duplicate job, or a job that arrives out of order, just recomputes the same current vector — safe to retry, safe to run twice. This matters because at-least-once queue delivery and worker restarts both produce duplicate jobs, and you don't want a re-embed race writing a stale vector over a fresh one.

Where this stops being right

  • A small catalogue with infrequent edits — a nightly full re-embed is simpler than wiring up triggers.
  • A feed that lands once a day — match the batch to the feed; there's nothing to gain from reacting faster than the data arrives.
  • Genuine near-real-time semantic freshness — a live editorial catalogue needs dedicated streaming, not a queue.

FAQ

Why not just re-embed on every write? It blocks catalogue updates on an external API call, and the feed stalls. Queue it instead.

Why filter to semantic-field changes? A price tick doesn't change what the embedding represents. Re-embedding on it is wasted spend.

When do we need change-data-capture tooling? When one worker can't keep up, or a second consumer needs the same change events. Otherwise filtered triggers are enough.

Does the queue need to be durable? Yes. If the worker crashes with jobs in flight and those jobs are lost, you're left with stale vectors and no signal that they're stale. Use a queue that persists jobs and re-delivers anything unacknowledged.

ISTRALLEN builds re-embedding pipelines that keep the index current against a live supplier feed without touching the write path; see AI for Retail.

See it in production
AI for Retail → Semantic search case study →
← All articles