Du prototype prometteur à la catastrophe d'architecture
Vous avez installé pgvector, stocké vos embeddings dans une table, et votre recherche sémantique retourne des résultats bluffants. L'équipe est enthousiaste. Puis vient la question fatidique : « C'est pour quand en production ? »
C'est là que la réalité rattrape l'enthousiasme. La distance entre « ça tourne sur mon laptop » et « ça tient la charge sur trois régions » est bien plus grande qu'anticipé. Et la réponse classique — migrer vers une base vectorielle dédiée, ajouter un service de recherche séparé, tout remodeler — revient à jeter le prototype pour repartir de zéro.
L'article d'Antony Pegg pour pgEdge (source originale) propose une autre voie : garder PostgreSQL comme fondation à chaque étape, sans changer de schéma.
Le prototype pgvector : simple, efficace… et fragile à l'échelle
La mise en place initiale est trompeusement simple :
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
category TEXT,
embedding vector(1536)
);
CREATE INDEX ON products USING hnsw (embedding vector_cosine_ops);
On stocke les embeddings aux côtés des données métier, on crée un index HNSW pour la recherche approximative par similarité, et on interroge avec l'opérateur <=> de pgvector :
SELECT name, description
FROM products
ORDER BY embedding <=> $1
LIMIT 10;
Ce modèle fonctionne remarquablement bien en développement. Les problèmes apparaissent quand le volume de données croît, que les requêtes concurrentes s'accumulent et que les utilisateurs se répartissent géographiquement.
Les trois murs que tout prototype IA sur Postgres finit par heurter :
- La latence : un index HNSW non partitionné ralentit avec le volume, et la distance physique entre l'utilisateur et la base se fait sentir.
- Le coût de stockage : les vecteurs 1536 dimensions sont lourds. Sur des millions de lignes, la facture monte vite.
- La concurrence : les workloads analytiques (batch d'embeddings) et OLTP (requêtes utilisateurs en temps réel) se marchent dessus.
L'architecture unifiée : Postgres à chaque étape, sans migration
L'approche défendue par pgEdge repose sur un principe fort : ne pas fragmenter l'architecture au prétexte de passer à l'échelle. Concrètement, cela se traduit par plusieurs leviers qui s'activent progressivement, sans toucher au schéma existant.
Partitionnement et indexation adaptés au volume
Avant de chercher une solution externe, PostgreSQL offre des mécanismes natifs puissants. Le partitionnement de table par plages d'identifiants ou par date permet de réduire la surface de recherche pour l'index HNSW. Les paramètres hnsw.ef_search et hnsw.m permettent d'ajuster le compromis précision/performance au plus près du besoin réel.
-- Ajuster la précision de recherche à la volée
SET hnsw.ef_search = 40;
Distribution multi-nœuds sans changement de schéma
L'enjeu principal de la mise en production multi-régions est la latence de lecture. Avec une architecture distribuée basée sur Postgres (comme celle que propose pgEdge), les données — y compris les vecteurs — sont répliquées sur plusieurs nœuds géographiques. Les lectures sont routées vers le nœud le plus proche de l'utilisateur, sans que l'application n'ait à changer sa logique de requête.
Le schéma ne change pas. Le code applicatif ne change pas. Seule la topologie de déploiement évolue.
Séparation des workloads sans fragmentation des données
Un des apports concrets de l'article concerne la cohabitation des workloads analytiques et transactionnels. Plutôt que de séparer les données dans des systèmes distincts (et de gérer la synchronisation), l'approche consiste à orienter les requêtes lourdes (génération d'embeddings en batch, reindexation) vers des nœuds secondaires, tout en réservant les nœuds primaires aux requêtes utilisateurs.
PostgreSQL supporte nativement ce routage via les connexions en lecture seule sur les réplicas. Pas besoin d'une infrastructure séparée.
Compression vectorielle pour réduire les coûts
PgEdge met en avant des gains de stockage allant jusqu'à 90% grâce à la compression des vecteurs. PostgreSQL 16+ introduit la quantification scalaire pour pgvector, qui réduit significativement l'empreinte mémoire des index sans dégrader fortement la précision :
CREATE INDEX ON products
USING hnsw (embedding vector_l2_ops)
WITH (m = 16, ef_construction = 64, quantization = 'sq8');
Cette option seule peut transformer un problème de coût en avantage concurrentiel.
Ce que ça change concrètement pour vos projets Symfony/PHP
Pour les équipes qui développent des applications RAG (Retrieval-Augmented Generation) avec Symfony et Doctrine, ce modèle a des implications directes :
- Doctrine reste utilisable : le schéma ne changeant pas, les entités et repositories existants continuent de fonctionner. L'embedding reste une colonne comme une autre, mappée avec un type personnalisé.
- Pas de double stack : inutile de gérer Pinecone ou Weaviate en parallèle de votre Postgres. Une seule connexion, une seule source de vérité.
- Déploiement progressif : on commence avec un seul nœud Postgres, on active la distribution quand le trafic le justifie. Pas de big bang architectural.
Le vrai bénéfice est opérationnel : moins de systèmes à monitorer, moins de surfaces de panne, moins de code de synchronisation à maintenir.
Conclusion
Le passage d'un prototype IA à un système de production n'implique pas nécessairement de tout réécrire. PostgreSQL, avec pgvector et une architecture de déploiement adaptée, peut accompagner la croissance sans forcer une migration vers des outils spécialisés.
L'article d'Antony Pegg le démontre avec des exemples concrets : le bon outillage, activé au bon moment, permet de faire évoluer l'infrastructure sans sacrifier le travail déjà accompli. C'est une philosophie qui s'aligne bien avec le développement Symfony : construire sur des fondations solides, et étendre progressivement.
📖 Source originale : Your AI App Works On Postgres. Now Make It Production-Ready Without Starting Over — Antony Pegg, pgEdge (juin 2026)