migration guide

Migrate from Algolia to altor-vec

Migrate if you're paying Algolia for a documentation or content-search use case where queries are natural-language phrases and your index is under a few hundred megabytes. Stay on Algolia if you need typo tolerance, faceted filtering, real-time re-indexing under 100 ms, or A/B testing — those are Algolia's genuine strengths and altor-vec does not replicate them.

When migration makes sense

What you give up

Be honest with your team before starting. altor-vec cannot replace these Algolia capabilities without significant custom work:

Step-by-step migration

Step 1 — Export all records from Algolia

Use the Algolia JavaScript client to page through your index and download every object. The browseObjects method handles pagination automatically.

// export-algolia.mjs  (run in Node.js)
import algoliasearch from 'algoliasearch';
import { writeFileSync } from 'fs';

const client = algoliasearch('YOUR_APP_ID', 'YOUR_ADMIN_API_KEY');
const index  = client.initIndex('YOUR_INDEX_NAME');

const records = [];
await index.browseObjects({
  query: '',
  attributesToRetrieve: ['objectID', 'title', 'content', 'url'],
  batch: (batch) => records.push(...batch),
});

writeFileSync('algolia-export.json', JSON.stringify(records, null, 2));
console.log(`Exported ${records.length} records`);

Step 2 — Generate embeddings for each record

Concatenate the fields that carry search meaning. For documentation, title + content works well. Use any embedding API you prefer — the example below uses the OpenAI embeddings endpoint.

// embed-records.mjs
import { readFileSync, writeFileSync } from 'fs';
import OpenAI from 'openai';

const openai  = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const records = JSON.parse(readFileSync('algolia-export.json', 'utf8'));

const BATCH = 100; // embed in batches to respect rate limits
const embedded = [];

for (let i = 0; i < records.length; i += BATCH) {
  const slice = records.slice(i, i + BATCH);
  const inputs = slice.map(r => `${r.title}\n\n${r.content ?? ''}`);

  const { data } = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: inputs,
  });

  slice.forEach((rec, j) => {
    embedded.push({
      id:        rec.objectID,
      title:     rec.title,
      url:       rec.url,
      embedding: data[j].embedding,   // 1536-dim float array
    });
  });

  console.log(`Embedded ${Math.min(i + BATCH, records.length)} / ${records.length}`);
}

writeFileSync('embedded-records.json', JSON.stringify(embedded));

Step 3 — Build the altor-vec index

Convert your embedded records into a binary index file that altor-vec can load in the browser.

// build-index.mjs
import altorVec from 'altor-vec/node';
import { readFileSync, writeFileSync } from 'fs';

const records = JSON.parse(readFileSync('embedded-records.json', 'utf8'));

const builder = new altorVec.IndexBuilder({ dimensions: 1536 });

for (const rec of records) {
  builder.add({
    id:        rec.id,
    vector:    new Float32Array(rec.embedding),
    metadata:  { title: rec.title, url: rec.url },
  });
}

const indexBuffer = await builder.build();
writeFileSync('public/search.altorindex', indexBuffer);
console.log(`Index written: ${(indexBuffer.byteLength / 1024).toFixed(1)} KB`);

Step 4 — Wire up browser search

Drop the previous Algolia InstantSearch widget and replace with altor-vec's browser API:

// search.js  (browser bundle)
import { AltorIndex } from 'altor-vec';

const idx = await AltorIndex.load('/search.altorindex');

document.getElementById('search-input').addEventListener('input', async (e) => {
  const query = e.target.value.trim();
  if (!query) return;

  const results = await idx.search(query, { topK: 8 });

  document.getElementById('results').innerHTML = results.map(r => `
    <a href="${r.metadata.url}">
      <strong>${r.metadata.title}</strong>
      <span>Score: ${r.score.toFixed(3)}</span>
    </a>
  `).join('');
});

Comparison at a glance

DimensionAlgoliaaltor-vec
Cost at scale~$1 / 1,000 search ops (paid plans)$0 per query (browser-side)
Server requiredYes — Algolia's hosted APINo — runs in WASM in the browser
Typo toleranceBuilt-in, configurableNone natively (embedding-fuzzy only)
Search typeKeyword + neural hybridDense vector (semantic)
Real-time updatesSeconds via API pushRebuild + redeploy index file
Tip: Build your altor-vec index as part of your CI pipeline. If you're on GitHub Actions, add a step that runs embed-records.mjs + build-index.mjs whenever your content changes, then uploads the resulting search.altorindex to your CDN origin.

Frequently asked questions

How much does migrating from Algolia to altor-vec save?

Algolia's pricing starts at roughly $1 per 1,000 search operations on paid plans. altor-vec runs entirely in the browser with no API calls at query time, so your per-search cost drops to zero. Your only ongoing cost is the one-time embedding generation when you build or refresh your index, which you can do with any embedding provider or a locally-run model.

Can I replicate Algolia's faceted search in altor-vec?

Not natively. altor-vec performs vector similarity search and does not have built-in facet aggregation. You can work around this by pre-filtering your document set in JavaScript before running a vector query, or by storing facet metadata alongside your embeddings and filtering results post-query. For complex filtering trees, Algolia's faceting remains superior.

Will there be downtime during migration?

Migration is additive, not a cutover. You can run both Algolia and altor-vec in parallel during your transition. Export your records, build the altor-vec index as a static asset, and shadow-test results before switching your UI. Most teams complete a shadow period in a few days with zero user-facing downtime.

What query types does altor-vec support compared to Algolia?

altor-vec performs dense vector similarity search — it finds results that are semantically similar to a query even when no keywords overlap. Algolia supports keyword search with typo tolerance and neural/hybrid search. If your users rely on exact phrase matching or typo correction, keep Algolia for those cases or implement a client-side fuzzy-match fallback alongside altor-vec.