Archiving vectors nobody searches
The collection has grown every month for two years and nothing has ever been removed from it, because removal was never anybody’s job. A large fraction of what is resident in memory right now has never appeared in a result set. You are paying full serving cost for records that are, operationally speaking, archived already — just archived in the wrong place.
Reducing record count is the only capacity mitigation that improves every ceiling at once: memory, disk, build time, and rebuild peak. It is also the one nobody reaches for, because it requires deciding what is not needed and that feels like a product decision rather than an ops one.
Finding what is never returned
You need per-record or per-group evidence, and you almost certainly are not collecting it. Options, in order of how much work they are.
Log the IDs you return. If your service logs result IDs — or can be made to, cheaply — a few weeks of logs give you the set of records that have ever been served. Everything else is a candidate. This is the most direct evidence and the easiest to defend when somebody objects.
Use the metadata you already filter on. If queries carry a date range, a source, or a status, and some values never appear, every record with those values is unreachable regardless of content. This requires no new instrumentation and is often enough on its own.
Look for structurally dead records. Documents whose source system has deleted them, chunks from a document version that has been superseded, records from a tenant that offboarded, duplicates from a re-ingest that did not clean up. These are not “rarely searched” — they are wrong to have, and they should go regardless of the capacity argument.
Ask the corpus, not the index. Your source of truth usually knows which documents are current. Records in the index whose source document no longer exists or is marked obsolete are the clearest possible candidates, and finding them is the reconciliation job in auditing a collection against your system of record.
Start collecting result-ID logs today even if you do not act for a quarter. The evidence has a warm-up period and you cannot backfill it.
What “archive” should mean
Four arrangements get called archiving. They differ in what you can get back and how fast.
| Arrangement | What is kept | Recovery |
|---|---|---|
| Delete from the index, keep the source corpus | Documents and chunks, not vectors | Re-embed and reload: hours |
| Delete from the index, keep the vectors in object storage | Vectors and payload | Reload and rebuild: shorter, model-locked |
| Move to a second, cold collection | Everything, searchable | Query the cold collection directly |
| Drop the partition | Whatever the partition held | Whatever you kept outside it |
The first is usually correct and is the one to default to, provided your source corpus is genuinely complete and re-embeddable — which is the prerequisite in reindexing without downtime and the reason that post insists on it. If you have that, archiving from the index costs you nothing permanent.
The third deserves consideration when the records must remain findable but not fast: a cold collection on cheaper, disk-resident storage, queried only when a user explicitly asks to search history. It keeps the capability and moves the cost off the hot path. It is also more moving parts and a second thing to operate, so only choose it if someone genuinely needs those results.
The fourth is the cheapest by a wide margin, and whether it is available to you was decided when you chose your layout — see partitioning by the filter you always use.
The procedure
- Define the archive rule in words first. “Chunks from documents whose source record is marked superseded” or “records in tenants with no queries for two quarters.” A rule you can state is a rule you can review, reverse, and automate. A one-off list of IDs is none of those.
- Count what the rule selects, and check it against the capacity problem. If the rule frees a small fraction, it is not worth the risk and you should widen it or choose a different mitigation. Use your measured bytes-per-record from sizing a vector index in memory to convert count into footprint before deciding.
- Have someone who owns the data confirm the rule. This is the step that makes it not your decision. Get it in writing, on the rule rather than on the ID list.
- Verify the archive is restorable before removing anything. Take a sample of the selected records, restore them into a scratch collection by the path you intend to rely on, and query them. An archive you have never restored from is a deletion with extra steps, and the same argument applies here as in backing up a vector database.
- Snapshot the collection. A bad archive rule is usually discovered after reclamation, when the removed records are unrecoverable from the index.
- Remove in batches, along partition or segment boundaries where possible. A drop along a boundary is instant and complete. Scattered deletes leave tombstones spread across every segment and reclaim nothing until compaction — which is the whole problem described in why deleting vectors doesn’t free memory.
- Reclaim deliberately. Deleting is not freeing. Trigger the reclamation mechanism your engine offers, confirm free space first, and expect to need compaction or a rebuild before the footprint actually moves. Do not report the capacity win until you have watched resident memory fall.
- Re-measure recall. Removing records changes the neighbourhood structure, and it can change results for queries that were being served by records you kept. Run the fixed query set, and expect some legitimate movement — refresh the expected IDs afterwards, or the probe will report the archive as an incident for weeks.
Rollback: restore from the step 5 snapshot, or reload the archived records by the path you verified in step 4. Hold that snapshot longer than your normal retention, because the way this goes wrong is that a rule turns out to have selected something needed, and it is noticed a month later by a user rather than a metric. Until the snapshot expires, the rollback is real; afterwards it is only as real as the archive.
Making it a standing process
The one-off cleanup is worth doing and it is not the win. The win is that record count stops being monotonic.
- Turn the rule into a scheduled job, aligned to a partition boundary so its reclamation is a drop rather than a compaction backlog.
- Chart records archived per month next to records added per month. These two numbers on one chart is the whole capacity conversation, and it belongs on the dashboard in what to monitor.
- Feed the net growth rate into the projection in capacity headroom for a growing index. A projection built on gross additions overstates the problem once archiving is running, and an overstated projection gets ignored.
- Review the rule when the product changes. A new feature that makes historical documents searchable again invalidates an archive rule silently, and the symptom is users reporting missing results rather than anything on a dashboard.
The framing that gets this approved: archiving is not about saving storage. It is about keeping the collection small enough that a rebuild still fits, which is the capability you lose first and notice last.