Azure OpenAI text-embedding-ada-002 deprecated — migration to text-embedding-3 (2026) — Fix Guide (2026) | AI Error Hub
Home Providers Azure OpenAI Embeddings model deprecated
Azure OpenAI Model Deprecation · Embeddings Severity: High HTTP 404

Azure OpenAI text-embedding-ada-002 — deprecated, reindex to text-embedding-3

Chat model deprecations are easy — swap the deployment. Embedding model deprecations force a complete reindex of every vector you have ever generated. This page is the migration playbook.

By Sana K. · Cloud AI Reliability Engineer Published 2026-07-26 Verified 2026-07-26

Quick fix (TL;DR)

Resolution: Azure OpenAI is deprecating text-embedding-ada-002 in favour of text-embedding-3-small (better/cheaper) and text-embedding-3-large (higher quality). Vectors from different models are not interchangeable — you must reindex your entire corpus. Fix by (a) choosing v3-small (default) or v3-large (quality-critical), (b) optionally using the new dimensions parameter to downscale, and (c) running the migration behind a dual-write flag before cutting over reads.

Real error messages you'll see

These are the exact strings returned by the Azure OpenAI service and its SDKs when this error occurs. Copy-paste-searching any of them should land on this page.

Python SDK — 404 on retired embeddings deployment
openai.NotFoundError: Error code: 404 - {'error': {'code': 'DeploymentNotFound', 'message': 'The API deployment for this resource does not exist.'}}
Wrong dimensions mixed in vector DB
pinecone.PineconeException: Vector dimension mismatch. Expected 1536, got 3072.
(text-embedding-ada-002 = 1536, text-embedding-3-large = 3072 by default)
Model version header on legacy deployment
HTTP/1.1 200 OK
x-ms-model-deprecation-notice: "text-embedding-ada-002 will be retired on 2026-06-15. Migrate to text-embedding-3-small (recommended) or text-embedding-3-large."

Reference

Azure OpenAI embedding models — quick comparison

ModelDefault dimensionsMTEB scoreCost per 1M tokensRecommended for
text-embedding-ada-002 (deprecated)153661.0$0.10Legacy — migrate off
text-embedding-3-small1536 (down to 512)62.3$0.02Default choice — cheaper + better
text-embedding-3-large3072 (down to 256)64.6$0.13Quality-critical retrieval, reranking

Reduced-dimension embeddings — trade-off

v3 models support the dimensions parameter to shorten output vectors while retaining most quality — critical for existing vector DBs with 1536-dim indexes.

ModelRequested dimensionsMTEB scoreNotes
text-embedding-3-small1536 (default)62.3Full quality
text-embedding-3-small51261.6Marginal drop for major storage savings
text-embedding-3-large3072 (default)64.6Full quality — most storage
text-embedding-3-large153664.1Drop-in replacement for ada-002 (same dims)
text-embedding-3-large25662.010× smaller, still beats ada-002

Root causes, ranked by frequency

Based on developer reports across Azure OpenAI SDK forums, GitHub issues, and Microsoft Q&A during 2025–2026.

  • 34%
    Application still targeting ada-002 deployment. Team assumed embedding models retire on the same slow cycle as chat models. ada-002 has a firm retirement date.
  • 20%
    Dimension mismatch on read after partial migration. Half the corpus is reindexed to v3-large (3072), half is still ada-002 (1536). Vector DB rejects queries or returns wrong results.
  • 14%
    Reindex not budgeted. Team plans model swap but forgets that every existing vector must be recomputed — could be billions of vectors, tens of thousands of dollars.
  • 10%
    No dual-write during migration. Cutover to new model without keeping the old index warm — one bug and you have no working retrieval.
  • 8%
    Downstream reranker trained on ada-002 embeddings. Distributions differ across models; rerankers, classifiers, and RAG scoring pipelines behave differently on v3 embeddings.
  • 6%
    Vector DB schema hardcoded to 1536. Pinecone, Weaviate, pgvector, Qdrant all have per-index dimension. New model with different dimensions requires a new index.
  • 5%
    Batch API used for reindex without dedup. Same source documents embedded multiple times, doubling cost.
  • 3%
    Cross-model similarity assumed transitive. Comparing ada-002 vectors against v3 vectors yields nonsense — cosine similarity does not translate across models.

Fixes — copy-paste solutions

Fix #1

Choose v3-small or v3-large based on your quality target

v3-small is the default choice — better than ada-002 at one-fifth the cost.

Start with text-embedding-3-small unless you have measured that v3-large produces meaningfully better retrieval on your evaluation set. For most RAG workloads, v3-small is the correct choice.

choose_model.py
"""Evaluation harness — measure v3-small vs v3-large on your data.

Run this ONCE with a representative sample of queries + labeled relevant docs
before committing to a model choice.
"""
import os
from openai import AzureOpenAI
from typing import List

client = AzureOpenAI(api_key="...", azure_endpoint="...", api_version="2024-10-21")

def embed(text: str, deployment: str, dimensions: int = None) -> List[float]:
    kwargs = {"model": deployment, "input": text}
    if dimensions:
        kwargs["dimensions"] = dimensions
    response = client.embeddings.create(**kwargs)
    return response.data[0].embedding

def cosine(a: List[float], b: List[float]) -> float:
    import math
    dot = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x * x for x in a))
    nb = math.sqrt(sum(x * x for x in b))
    return dot / (na * nb)

def recall_at_k(queries, docs, deployment, k=10, dimensions=None):
    """queries: [(query_text, relevant_doc_ids)]; docs: {doc_id: text}"""
    doc_embs = {i: embed(t, deployment, dimensions) for i, t in docs.items()}
    hits = 0
    for query, relevant in queries:
        qe = embed(query, deployment, dimensions)
        scored = sorted(doc_embs.items(), key=lambda x: cosine(qe, x[1]), reverse=True)[:k]
        if any(doc_id in relevant for doc_id, _ in scored):
            hits += 1
    return hits / len(queries)

# Build eval set from your production data (100-1000 labeled queries is enough)
queries = [...]   # [(query, {relevant_doc_ids})]
docs = {...}      # {doc_id: doc_text}

for cfg in [
    ("text-embedding-3-small", None),
    ("text-embedding-3-small", 512),
    ("text-embedding-3-large", 1536),
    ("text-embedding-3-large", None),  # 3072
]:
    deployment, dims = cfg
    score = recall_at_k(queries, docs, deployment, k=10, dimensions=dims)
    print(f"{deployment} ({dims or 'default'}): recall@10 = {score:.3f}")
Do not skip the evaluation. v3-large is 6× more expensive at storage time and 5-10% more at query time — worth it for some workloads, wasteful for others. A 100-query eval set takes 30 minutes and saves months of pain.
Fix #2

Reindex with dual-write to avoid downtime

Keep the old index serving reads while the new one fills.

Migrate in three phases: (1) dual-write to both old and new indexes; (2) run the full backfill of historical data; (3) shift reads to the new index; (4) decommission the old. This bounds the risk of a bad model choice.

reindex_migration.py
"""Dual-write migration from ada-002 to text-embedding-3-large."""
import os
from openai import AzureOpenAI

client = AzureOpenAI(api_key="...", azure_endpoint="...", api_version="2024-10-21")

# Phase flags — controlled via env or feature flag service
DUAL_WRITE = os.getenv("EMBEDDINGS_DUAL_WRITE") == "true"
READ_FROM_NEW = os.getenv("EMBEDDINGS_READ_FROM_NEW") == "true"

# Deployments
DEPLOYMENT_OLD = "ada002-legacy"           # to be retired
DEPLOYMENT_NEW = "text-embedding-3-large"

# Vector DBs (simplified — pinecone, weaviate, etc.)
index_old = ...  # 1536-dim
index_new = ...  # 3072-dim (or 1536 if you use dimensions=1536 on 3-large)

def embed(text: str, deployment: str, dimensions: int = None):
    kwargs = {"model": deployment, "input": text}
    if dimensions:
        kwargs["dimensions"] = dimensions
    return client.embeddings.create(**kwargs).data[0].embedding

def upsert_document(doc_id: str, text: str):
    """Called at write time. In dual-write, writes to both indexes."""
    # Always write to the new index
    emb_new = embed(text, DEPLOYMENT_NEW)  # 3072-dim
    index_new.upsert(doc_id, emb_new, metadata={"text": text})

    if DUAL_WRITE:
        emb_old = embed(text, DEPLOYMENT_OLD)
        index_old.upsert(doc_id, emb_old, metadata={"text": text})

def search(query: str, k: int = 10):
    """Called at read time. Dispatches to the active index."""
    if READ_FROM_NEW:
        qe = embed(query, DEPLOYMENT_NEW)
        return index_new.query(qe, top_k=k)
    else:
        qe = embed(query, DEPLOYMENT_OLD)
        return index_old.query(qe, top_k=k)

# Backfill script — run once per historical batch
def backfill_batch(doc_batch):
    """Backfill new index from historical corpus."""
    texts = [d["text"] for d in doc_batch]
    response = client.embeddings.create(model=DEPLOYMENT_NEW, input=texts)
    for doc, emb in zip(doc_batch, response.data):
        index_new.upsert(doc["id"], emb.embedding, metadata=doc.get("metadata", {}))
Cost note: reindexing 100M documents at 500 tokens each = 50B tokens. On text-embedding-3-small ($0.02/1M) that is $1,000; on 3-large ($0.13/1M) that is $6,500. Use Batch API for the initial backfill — 50% off.
Fix #3

Use dimensions parameter to keep 1536-dim index

Drop-in upgrade: same dimensionality, better quality.

If your vector database index is hardcoded to 1536 dimensions and re-indexing to 3072 is not practical, use v3-large with dimensions=1536. You get better quality than ada-002 without changing your index schema.

dropin_upgrade.py
from openai import AzureOpenAI

client = AzureOpenAI(api_key="...", azure_endpoint="...", api_version="2024-10-21")

# text-embedding-3-large truncated to 1536 dims
# Beats ada-002 quality, same dimensions, same index schema
def embed_v3_dropin(texts: list) -> list:
    response = client.embeddings.create(
        model="text-embedding-3-large",  # your deployment name for 3-large
        input=texts,
        dimensions=1536,   # match your existing index dimensionality
    )
    return [d.embedding for d in response.data]

# Verify quality parity before switching
sample_texts = ["A dog barks", "A canine vocalises loudly"]
old_vecs = ...   # from ada-002
new_vecs = embed_v3_dropin(sample_texts)

# Cosine similarity between semantically similar sentences should be higher on v3
print("v3-large @1536:", cosine(new_vecs[0], new_vecs[1]))
print("ada-002:      ", cosine(old_vecs[0], old_vecs[1]))
Even at 1536 dimensions, v3-large outperforms ada-002 on MTEB benchmarks (64.1 vs 61.0). If you cannot expand your index, this is the correct upgrade path.

Prevention checklist

Ship these seven safeguards once and this error stops appearing in your logs.

  • Track the retirement date for every embedding model in production — put it in Ops calendars.
  • Never mix embeddings from different models in the same vector database index.
  • Use Batch API for reindexing when latency does not matter — 50% cost saving over real-time.
  • Version your vector index name (docs-v1, docs-v2) to enable side-by-side migration.
  • Log the model + dimensions on every write to your vector DB metadata — you will thank yourself during migration.
  • Evaluate v3-small first — it beats ada-002 at 1/5th the cost for most use cases.
  • Downstream classifiers or rerankers on top of embeddings must be re-trained after a model change — they are model-specific.

Frequently asked questions

No — cosine similarity across different embedding models is meaningless. The models learn different geometries. Even similar sentences will get random-looking scores when compared across models. Reindex before mixing.
At 500 tokens per document and 3-small's throughput, a well-tuned pipeline handles 5-10K docs/second per deployment. A billion documents completes in 30-60 hours on Batch API. Real-time is faster per hour but consumes RPM/TPM quota you probably need for live traffic.
Not for the migration itself, but consider it: v3 models handle longer chunks better than ada-002. If you're reindexing anyway, this is a good time to test larger chunk sizes and see if retrieval quality improves.
No — v3 rolled out to regions in stages. As of 2026, it is in all major regions (East US, West Europe, Sweden Central, Australia East, etc.) but check availability before you commit. Some newer regions get v3 first and never got ada-002 GA.
v3 was released with fixed versions (small and large) and Azure has not published mid-version updates. Assume stability but track the deprecation feed. If v4 arrives, expect at least 12 months of parallel availability.

Get the weekly AI-error digest

New fixes, provider status recaps, and one deep tutorial — every Tuesday. 8,400+ engineers.