DuckDB : votre RAG tient dans un fichier, pas dans un cluster

Un chef de projet me détaille fièrement son architecture RAG la semaine dernière. Pinecone Starter à 200 € par mois, Elasticsearch en autoscaling sur AWS, Postgres managed pour les métadonnées, FastAPI sur ECS Fargate, le tout orchestré par LangChain. Volume effectivement indexé : 84 000 chunks issus des manuels techniques de son entreprise. Soit, en HNSW float32 sur 1536 dimensions, environ 500 Mo de vecteurs. Ce qu’un MacBook M1 d’entrée de gamme tient dans sa RAM sans broncher pendant que tournent VS Code, Chrome et Spotify.

Bienvenue dans la grande arnaque infrastructurelle du RAG d’entreprise.

La stack qu’on vous vend

L’architecture canonique du RAG d’entreprise version 2024 tient en quatre services distincts, vendus comme « best of breed » par à peu près tous les éditeurs et tous les consultants. Pour répondre à une requête utilisateur du type « retrouve-moi les factures du client X mentionnant une pénalité de retard », il vous faut typiquement :

  1. Un vector store dédié pour la recherche sémantique. Pinecone (SaaS, ~70 à 200 €/mois en entrée), Qdrant ou Weaviate (self-hosted, container Docker à maintenir, RAM gourmande, monitoring à installer). Son rôle unique : stocker des vecteurs d’embeddings et faire de la similarité cosinus.
  2. Un moteur full-text pour la recherche par mots-clés. Elasticsearch en tête, avec ses 2 Go de RAM minimum et sa JVM à régler, ou Meilisearch / Typesense en plus léger. Indispensable parce que la recherche sémantique seule rate systématiquement les termes exacts : si vous cherchez « facture FR-2025-04711 », un embedding vous renverra des factures vaguement similaires, pas la bonne. BM25 trouve le numéro exact. Tout RAG sérieux a besoin des deux mécanismes en parallèle.
  3. Une base relationnelle pour stocker les métadonnées tabulaires et permettre le filtrage structuré. Parce que ni le vector store ni l’index full-text ne savent répondre à « facture du client 42, payée, datée entre janvier et mars 2025, montant supérieur à 1000 € ». Donc Postgres ou MySQL en plus, avec la cohérence à maintenir entre les trois systèmes.
  4. Une couche d’orchestration pour faire dialoguer tout ça. LangChain, LlamaIndex, ou votre propre code FastAPI. Sa charge cognitive devient rapidement intense : recevoir la requête, appeler le vector store, appeler l’index BM25, appeler la base SQL, récupérer les métadonnées de tous les candidats, filtrer, faire le re-ranking hybride par Reciprocal Rank Fusion, renvoyer le top-K final, appeler le LLM avec le contexte assemblé.

Quatre services à monitorer. Trois sources de données à synchroniser. Une couche de réconciliation custom à coder et maintenir. Trois sauvegardes à orchestrer de façon cohérente sous peine d’index désaligné. Et bien sûr, trois appels réseau qui s’additionnent en latence sur chaque requête utilisateur, avec une gestion d’erreurs partielles digne d’un système distribué bancaire : « le vector store répond mais pas Elasticsearch, je fais quoi ? ».

Coût mensuel sur un projet de taille moyenne : entre 150 et 400 € d’infrastructure cloud. Compétences requises pour opérer : un DevOps, un data engineer, un dev backend. Temps de mise en prod : entre deux et quatre semaines de plomberie pure, avant même d’avoir indexé le premier document utile.

C’est la stack qu’on enseigne aujourd’hui dans 90 % des tutoriels RAG, qu’on retrouve dans 90 % des PoC d’agences, et qu’on facture à 90 % des clients PME qui n’en avaient pas besoin.

DuckDB, ou l’enterrement de la complexité

DuckDB est une base de données analytique embarquée, créée en 2019 au sein du Centrum Wiskunde & Informatica d’Amsterdam, et devenue en cinq ans l’outil de référence du data engineering moderne. Le pitch tient en une phrase : c’est SQLite, mais pour l’analytique au lieu du transactionnel.

Comme SQLite : zéro serveur, zéro configuration, une seule bibliothèque embarquée dans votre application, un fichier .duckdb qui contient toute votre base. Aucun daemon à lancer, aucun port à ouvrir, aucun droit utilisateur à gérer, aucune mise à jour à coordonner.

Contrairement à SQLite : moteur en colonnes (et non en lignes), vectorisé, optimisé pour les requêtes qui agrègent des millions de lignes en quelques millisecondes. Le SQL est très proche de PostgreSQL : fenêtres analytiques, CTE récursives, types ARRAY et STRUCT natifs, JSON intégré, plus quelques sucres syntaxiques bien pensés qu’aucun autre SGBD ne propose (SELECT * EXCLUDE, GROUP BY ALL, requête directe d’un CSV ou d’un Parquet distant).

Tout cela est connu de la communauté data depuis trois ans. Ce qui l’est moins, c’est la révolution silencieuse qui s’est produite sur le terrain du RAG depuis 2024 : DuckDB est devenu l’un des outils de référence pour cet usage spécifique, et ce pour cinq raisons concrètes.

Ce que DuckDB reçoit, ce que DuckDB rend

Avant d’attaquer le SQL, levons une ambiguïté qui revient systématiquement dans les questions de mes lecteurs : DuckDB stocke trois choses dans la même ligne, et il en reçoit trois en entrée.

Pour chaque morceau de document indexé (typiquement un chunk de 200 à 800 tokens), votre code applicatif envoie à DuckDB :

  1. Le texte plain du chunk, en UTF-8 standard, dans une colonne TEXT. C’est ce qui sera renvoyé au LLM en contexte au moment de la génération.
  2. Le vecteur d’embedding précalculé du chunk, sous forme de tableau de flottants, dans une colonne FLOAT[N]. C’est l’index sémantique du texte, c’est lui qui permet la recherche par similarité.
  3. Les métadonnées structurées (date, auteur, client, source, page, langue…) dans des colonnes SQL classiques. C’est ce qui permet le filtrage avant ou après la recherche vectorielle.

Point crucial qui surprend les débutants : DuckDB ne calcule pas les embeddings, exactement comme PostgreSQL avec pgvector ou comme Pinecone. La vectorisation est une étape applicative qui se passe en amont, généralement via un appel API à OpenAI, Voyage AI, Mistral Embed, Cohere, ou un modèle local via SentenceTransformers. DuckDB reçoit le vecteur déjà calculé et le stocke. Idem à la requête : votre application vectorise la question utilisateur avec le même modèle d’embedding que celui utilisé à l’indexation (changer de modèle entre les deux étapes casse complètement la recherche), puis envoie ce vecteur à DuckDB pour comparaison.

Concrètement, une insertion ressemble à ceci :

INSERT INTO docs (id, content, embedding, source_doc, page, date, client_id)
VALUES (
  42,
  'Le contrat prévoit une pénalité de retard de 0,5 % par jour ouvré au-delà du délai contractuel de 30 jours suivant émission de la facture.',
  [0.0231, -0.1872, 0.0938, ...]::FLOAT[1536],  -- vecteur précalculé en amont
  'contrat_Dupont_2025-03.pdf',
  4,
  '2025-03-15',
  42
);Langage du code : SQL (Structured Query Language) (sql)

Le pipeline amont qui produit ces trois entrées (extraction PDF, chunking, vectorisation) est un sujet à lui seul. Je l’ai détaillé dans deux articles dédiés que je vous renvoie à lire si vous démarrez de zéro : Le RAG expliqué comme personne ne le fait pour la vision d’ensemble du pipeline, et Le parsing visuel : pourquoi vos PDF sabotent votre RAG pour l’étape critique de l’extraction de texte propre depuis vos documents source.

Tout le reste de cet article suppose qu’on en est là : vous avez vos chunks de texte, vos vecteurs précalculés, vos métadonnées. La question qu’on traite à partir d’ici, c’est : où je les mets et comment je les requête ?

La recherche vectorielle native

L’extension vss (Vector Similarity Search), maintenue par l’équipe DuckDB elle même bien que toujours qualifiée d’experimental dans la documentation, ajoute à DuckDB un index HNSW (Hierarchical Navigable Small World), qui est l’algorithme standard de la recherche vectorielle approximative, le même que celui utilisé par Qdrant, Pinecone ou pgvector. Le choix du modèle d’embedding qui alimente cet index reste évidemment une décision indépendante, à instruire en amont. Installation et usage :

INSTALL vss; LOAD vss;

CREATE TABLE docs (
  id INTEGER,
  content TEXT,
  date DATE,
  client_id INTEGER,
  embedding FLOAT[1536]
);

CREATE INDEX hnsw_idx ON docs USING HNSW (embedding);

-- Recherche des 5 chunks sémantiquement les plus proches
SELECT id, content,
       array_cosine_similarity(embedding, ?::FLOAT[1536]) AS score
FROM docs
ORDER BY score DESC
LIMIT 5;Langage du code : SQL (Structured Query Language) (sql)

Vous obtenez un vector store complet, fonctionnel, performant, en une bibliothèque embarquée de 30 Mo. Pour la majorité des projets RAG d’entreprise (moins de 10 millions de chunks indexés), c’est strictement équivalent en performance aux solutions dédiées, et infiniment plus simple à déployer.

Le RAG hybride trivialisé

C’est sans doute le point où DuckDB écrase la concurrence. L’extension fts ajoute la recherche full-text BM25. Combinée à vss et au moteur SQL standard, elle permet d’écrire en une seule requête ce qui demandait toute une chorégraphie applicative dans la stack à quatre services :

SELECT content,
       array_cosine_similarity(embedding, ?::FLOAT[1536]) AS vec_score,
       fts_main_docs.match_bm25(id, 'requête utilisateur') AS bm25_score
FROM docs
WHERE date >= '2025-01-01'
  AND client_id = 42
  AND langue = 'fr'
ORDER BY (0.7 * vec_score + 0.3 * bm25_score) DESC
LIMIT 10;Langage du code : SQL (Structured Query Language) (sql)

Recherche sémantique. Recherche BM25. Filtrage structuré sur trois métadonnées. Re-ranking pondéré. Top-K final. Tout en une requête SQL, en local, en quelques millisecondes. Pas d’appel réseau, pas de réconciliation côté Python, pas de transactions distribuées à coordonner. Comparez avec la stack canonique précédente : on est passé de quatre services à orchestrer à une instruction SQL de huit lignes. J’avais déjà ouvert le débat sur les alternatives SQL/BM25 à la base vectorielle dédiée ; DuckDB en fournit désormais l’implémentation canonique.

Le pattern Text-to-SQL qui ferme la boucle

L’autre usage massif de DuckDB dans le monde de l’IA, c’est le Text-to-SQL augmenté par RAG. Le pattern type :

  1. L’utilisateur pose une question en langage naturel (« quels sont les 10 produits avec la plus forte marge sur le trimestre écoulé ? »).
  2. Un RAG récupère le schéma pertinent de la base (tables, colonnes, exemples de valeurs, descriptions métier) depuis un vector store.
  3. Le LLM génère la requête SQL appropriée.
  4. DuckDB l’exécute directement, parce qu’il sait lire du CSV, du Parquet, du JSON, de l’Excel, et même se connecter à un MySQL ou un Postgres distant en lecture seule, le tout sans ETL préalable.
  5. Le LLM commente le résultat retourné.

DuckDB s’impose dans cette stack parce qu’il coche toutes les cases simultanément. Son dialecte SQL est très standard, donc les LLM publics (Claude, GPT, Gemini) le maîtrisent mieux que les dialectes exotiques. Son exécution est trivialement sandboxable en mode read-only, ce qui évite qu’un LLM créatif n’exécute un DROP TABLE. Ses messages d’erreur sont explicites, ce qui permet la boucle de self-correction (le LLM regénère la requête à partir du message d’erreur). Et son coût marginal d’exécution est nul, puisqu’il n’y a ni connexion réseau ni autorisation à valider.

Tous les frameworks IA majeurs ont désormais une intégration DuckDB native : LangChain, LlamaIndex, Vanna.ai, PandasAI, dbt, Dagster. Ce n’est pas une mode de niche, c’est devenu un standard de fait que personne n’a annoncé bruyamment.

Le bilan opérationnel comparé

Voici, pour un projet RAG d’entreprise de taille moyenne (quelques centaines de milliers de chunks indexés, charge applicative typique d’une PME), le delta concret entre les deux approches :

CritèreStack à 4 servicesStack DuckDB
Services à monitorer40 (bibliothèque embarquée)
RAM serveur typique8 à 16 Go1 à 4 Go
Coût mensuel infra150 à 400 €/mois~20 €/mois (juste l’app)
Temps de mise en prod2 à 4 semaines2 à 4 jours
Sauvegardes3 systèmes à synchroniser1 fichier à rsync
Compétences nécessairesDevOps + data engineer + devDev seul
Latence d’une requête hybride100 à 300 ms (3 appels réseau + réconciliation)5 à 30 ms (local)
Mise à jour atomiqueTransactions distribuées complexesTransaction SQL triviale

Un facteur 10 à 20 sur le coût d’infrastructure. Un facteur 5 à 10 sur la consommation RAM. Un facteur 10 sur la latence. Un facteur 5 sur le temps de mise en prod. Et une réduction d’effectif technique qui fait passer le projet de « il faut une équipe » à « un développeur senior s’en occupe le mardi après-midi ».

Pour des performances strictement équivalentes en dessous de 10 millions de vecteurs indexés. Soit le périmètre exact de 95 % des projets RAG d’entreprise réels.

L’argument souverain qui clôt le débat

Au delà de la simple économie d’infrastructure, DuckDB règle un problème que la stack canonique aggrave systématiquement : la localisation des données.

Quand vous indexez les manuels internes d’un client, ses tickets support, ses factures, ses contrats, dans Pinecone, vous envoyez par construction l’intégralité du contenu sémantique de ces documents vers un service hébergé aux États-Unis, donc juridiquement soumis au CLOUD Act. Les embeddings ne sont pas chiffrés au repos pour la requête, ce sont des représentations vectorielles directement exploitables. N’importe qui ayant accès à votre index Pinecone peut reconstruire approximativement le contenu de vos documents originaux par inversion d’embedding (technique documentée depuis 2023, plusieurs papiers publics).

Pour un client soumis au RGPD, à HDS, à NIS 2, ou tout simplement attentif à la confidentialité de ses documents stratégiques, c’est une bombe à retardement contractuelle. Le DPO ouvre un ticket, le projet est gelé pendant six mois, le PoC enterré au passage.

DuckDB renverse complètement cette équation. La base tient dans un fichier local. Le serveur sur lequel elle tourne peut être un VPS européen à 15 € par mois, ou même un container Docker sur le NAS du client. Les embeddings ne quittent jamais l’infrastructure du client. Les seules sorties réseau sont les appels API au LLM pour la génération finale, qui peuvent eux-mêmes être routés vers Claude sur AWS Bedrock Paris, Mistral en France, ou un modèle open source local (Llama, Mixtral, Qwen) si la sensibilité l’exige.

C’est l’application directe de ce que j’écrivais dans mon article IA souveraine : pourquoi l’open source local est devenu le seul choix d’indépendance en 2026. L’infrastructure data du RAG doit suivre la même logique que le modèle d’inférence. Sortir vos embeddings de chez vous, c’est exactement aussi grave que sortir vos prompts.

« Et le scaling horizontal alors ? »

C’est la question légitime du développeur backend qui a lu jusqu’ici. Si DuckDB est une bibliothèque embarquée et non un serveur, comment ça se comporte quand mon application FastAPI scale sur dix conteneurs derrière un load balancer ?

Le pattern de déploiement éprouvé tient en trois mots : ouverture concurrente en lecture seule. Le fichier .duckdb qui contient votre index est typiquement stocké sur un volume partagé (NFS, EFS sur AWS, Azure Files, ou volume Kubernetes RWX) ou chargé en RAM au démarrage de chaque conteneur depuis un bucket S3 ou MinIO compatible. DuckDB supporte parfaitement l’ouverture simultanée du même fichier en mode READ_ONLY par N processus distincts, qui peuvent tous lire et requêter en parallèle sans verrou ni coordination.

import duckdb
con = duckdb.connect('/mnt/shared/rag-index.duckdb', read_only=True)
# Plusieurs conteneurs FastAPI peuvent faire ça simultanément
Langage du code : PHP (php)

L’indexation, elle, se fait dans un job batch séparé (cron nocturne, GitHub Action, pipeline dbt) qui produit un nouveau fichier .duckdb versionné. Les conteneurs applicatifs basculent vers la nouvelle version au démarrage suivant, ou via un hot-reload si vous y tenez. C’est exactement le pattern build-deploy-serve qu’on appliquait déjà aux index Lucene il y a quinze ans, en infiniment plus simple à opérer.

Pour 99 % des charges B2B PME, un seul conteneur applicatif avec un fichier .duckdb local en lecture seule sert plusieurs centaines de requêtes par seconde sans broncher. Le scaling horizontal n’est même pas une question.

Les limites honnêtes

Aucun outil n’est universel, et je préfère lister les limites avant que les commerciaux de Pinecone ne s’en chargent.

Le statut « experimental » de l’extension vss. Soyons précis : malgré son adoption massive en production depuis 2024, l’équipe DuckDB qualifie toujours officiellement vss comme experimental dans sa documentation, y compris dans les releases récentes de 2026. En pratique, les performances sont au rendez-vous et la stabilité ne pose pas de problème observé sur le terrain. Mais cela signifie deux choses : les évolutions de l’API peuvent encore introduire des ruptures de compatibilité sur des montées de version, et les SLA fournisseur que vous pourriez signer auprès de votre client doivent en tenir compte. Pour un PoC ou une mise en production raisonnée, cela ne change rien. Pour une stack core business critique avec SLA contractuel à 99,99 %, vous écrivez un paragraphe explicite dans la documentation technique.

Le prefiltering HNSW. Point technique précis qui fera plaisir aux puristes : par défaut, l’extension vss applique les clauses WHERE après la recherche dans l’index HNSW, et non avant. Conséquence concrète : sur un filtre métadonnée très sélectif (typiquement « documents du client 42, datés de 2025 ») combiné à une recherche vectorielle à K=10, vous pouvez vous retrouver avec moins de 10 résultats finaux, parce que l’index HNSW a remonté 10 candidats sémantiquement proches, dont seulement 3 satisfont le filtre métadonnée. Les vector stores dédiés (Qdrant, Weaviate, pgvector récent) gèrent le prefiltering nativement et n’ont pas ce souci. Une extension communautaire hnsw_acorn corrige cette limite côté DuckDB, mais elle n’est pas encore intégrée au core. En pratique, on contourne en augmentant K (K=100 au lieu de K=10) puis en filtrant après. Surcoût de calcul négligeable sur des volumes PME. Et il existe une astuce supplémentaire que les puristes apprécieront : DuckDB étant une bête de course sur le scan colonne, quand le filtre métadonnée est très restrictif (typiquement un seul client qui ne pèse que quelques milliers de lignes sur le total), il est souvent plus rapide et plus précis de désactiver l’index HNSW et de faire un scan linéaire exact sur le sous-ensemble filtré, plutôt que de passer par l’index approximatif. On force ça avec un simple SET hnsw_enable_experimental_persistence = false sur la session, ou en utilisant un sous-SELECT qui matérialise d’abord le filtre. Sur des volumes massifs avec filtres très sélectifs, c’est le seul scénario où la stack à quatre services garde un avantage technique théorique aujourd’hui, et encore, ce contournement le neutralise dans la plupart des cas.

DuckDB n’est pas conçu pour les écritures concurrentes haute fréquence. Un seul écrivain à la fois sur le fichier. Donc inutile d’imaginer DuckDB comme backend de votre boutique WooCommerce. Sa zone de pertinence reste analytique : un script ou une application qui ouvre la base, exécute ses requêtes lourdes, et ferme.

L’index HNSW de l’extension vss n’est pas incrémental sur les insertions massives. Si vous indexez un flux Twitter en temps réel à 10 000 nouveaux vecteurs par minute, vous devrez reconstruire l’index périodiquement. Pas dramatique sur du batch nocturne, rédhibitoire sur du streaming temps réel.

Au delà de 50 à 100 millions de vecteurs, vous quittez le périmètre de pertinence de DuckDB et il devient légitime de passer à un vector store dédié. À cette échelle, d’autres pathologies plus fondamentales du RAG commencent d’ailleurs à se manifester, au point que le choix du moteur de stockage devient secondaire. Mais soyons honnêtes : si votre projet indexe 100 millions de vecteurs, vous n’êtes plus une PME et vous avez les moyens d’avoir une équipe data dédiée.

La gestion multi-tenants à très haute concurrence (1000 requêtes par seconde simultanées sur la même base) n’est pas la cible. Si votre application doit servir 1000 utilisateurs concurrents sur la même base RAG, vous êtes dans le rare 1 % des cas qui justifient effectivement une stack dédiée. Le SaaS B2C grand public est typiquement dans cette catégorie. Le B2B PME français, qui représente l’écrasante majorité des projets, n’y est jamais.

Voilà. Ces limites couvrent peut être 5 % des projets RAG d’entreprise. Les 95 % restants n’avaient strictement aucune raison de payer 200 € par mois à Pinecone.

La citation qui résume tout

Jordan Tigani, ex-architecte de BigQuery chez Google et aujourd’hui co-fondateur de Motherduck (la version cloud de DuckDB), a publié en 2023 un essai resté célèbre dans le milieu data : Big Data is Dead. Sa thèse : la majorité des projets data dans le monde tournent sur des volumes qui tiennent dans la RAM d’un ordinateur portable. On a normalisé l’usage de Spark, Hadoop, Snowflake et Kubernetes par habitude, par mimétisme, par signalement de compétence, mais quasiment jamais par nécessité réelle.

Cette analyse se transpose intégralement au RAG. La majorité des projets RAG d’entreprise indexent moins de 100 000 documents. Cela tient dans 2 Go de RAM. Cela tient dans un fichier sur un NAS. Cela tient dans une instance Hetzner à 5 € par mois.

La stack à quatre services qu’on vend aujourd’hui à toutes les PME françaises n’existe pas pour résoudre un problème technique. Elle existe pour vendre du SaaS récurrent, justifier des prestations DevOps, gonfler des budgets projets, et permettre à des consultants de facturer des « architectures cloud-native » sur des cas d’usage qui ne le méritent pas.

DuckDB n’est pas une alternative technique. C’est une rééducation économique du marché.

Pour démarrer cet après-midi

Si vous lisez ceci en ayant un projet RAG qui dort dans un PowerPoint, ou pire, en train de payer 300 € par mois à un combo Pinecone + Elasticsearch + RDS pour 50 000 chunks, voici la procédure :

brew install duckdb     # macOS
apt install duckdb      # Debian/Ubuntu

duckdb ma_base.duckdbLangage du code : Bash (bash)

Puis dans le REPL :

INSTALL vss; LOAD vss;
INSTALL fts; LOAD fts;Langage du code : SQL (Structured Query Language) (sql)

Vous venez d’installer un vector store, un moteur full-text et une base relationnelle SQL. Le tout en trois commandes, sans ouvrir un seul port, sans créer un seul compte cloud, sans signer un seul DPA. Maintenant chargez vos embeddings et écrivez votre première requête hybride.

Le RAG d’entreprise vient de redevenir ce qu’il aurait toujours dû être : un problème de SQL bien écrit, pas un projet d’infrastructure à six chiffres.

Reste à expliquer à votre client pourquoi vous facturez 3 jours au lieu de 3 semaines. C’est, comme toujours, le vrai problème.

Et au passage, c’est aussi la définition exacte de ce qu’est devenu un ingénieur senior en 2026. La valeur ne se mesure plus au nombre de microservices Kubernetes qu’il sait empiler, ni au nombre de tableaux de bord Grafana qu’il sait orchestrer. Elle se mesure au nombre de lignes d’infrastructure qu’il sait supprimer pour résoudre exactement le même problème. À l’opposé exact du vibe coding où l’on empile des couches d’abstraction jusqu’à l’absurde, les meilleurs architectes data que je connais en 2026 sont ceux qui rendent leur propre rôle progressivement inutile, en transformant des stacks distribuées de 12 services en scripts Python de 200 lignes qui tiennent dans un fichier.

C’est moins glamour à mettre sur LinkedIn. C’est infiniment plus rentable pour le client. Et c’est exactement ce que la moitié de l’industrie tech refuse encore d’admettre, parce que sa structure de revenus repose sur l’inverse.


Écrivez quelques éclats d'âme...

Dans l'ombre vacillante d'une chandelle, où les murmures du vent se mêlent aux secrets d'un vieux parchemin, je vous invite à tisser une toile de mots. Écrivez quelques éclats d'âme – rêve, étoile, abîme, étreinte, brume – et laissez-les danser sur la page, comme des lucioles dans une nuit d'encre. Que diriez-vous de les entrelacer dans une phrase, un souffle, une histoire ?

S’abonner
Notification pour
guest
0 Commentaires
Le plus ancien
Le plus récent Le plus populaire