28 janvier 2026
10 Fonctionnalités Cachées de Convex que Personne n'Utilise

Convex, c'est le backend qui a révolutionné ma façon de coder. Mais après des mois à creuser la doc, j'ai découvert des pépites cachées que 90% des développeurs n'exploitent pas.
En tant que Product Engineer, je vais vous révéler les 10 features qui changent tout.
1. Scheduled Functions : Le Cron Killer
Oubliez les cron jobs à configurer sur un serveur. Convex permet de planifier des fonctions directement depuis votre code.
1// Planifier une fonction dans 5 minutes2await ctx.scheduler.runAfter(5 * 60 * 1000, internal.emails.sendReminder, {3 userId: args.userId,4});5
6// Planifier à une date précise7await ctx.scheduler.runAt(new Date("2026-02-01T09:00:00Z"), internal.reports.generate, {8 reportId: args.reportId,9});La magie ? Si votre mutation réussit, la fonction est garantie de s'exécuter. Si elle échoue, rien n'est planifié. Atomicité parfaite.
- Jusqu'à 1000 fonctions planifiées simultanément
- Délai de quelques millisecondes à plusieurs années
- Visible dans le dashboard Convex
2. Cron Jobs Natifs
Pour les tâches récurrentes, Convex a son propre système de crons. Créez un fichier convex/crons.ts :
1import { cronJobs } from "convex/server";2import { internal } from "./_generated/api";3
4const crons = cronJobs();5
6// Toutes les heures7crons.interval("sync-data", { hours: 1 }, internal.sync.pullFromAPI);8
9// Chaque jour à 9h UTC10crons.daily("daily-report", { hourUTC: 9, minuteUTC: 0 }, internal.reports.daily);11
12// Syntaxe cron classique13crons.cron("cleanup", "0 0 * * 0", internal.cleanup.weeklyPurge);14
15export default crons;Avantage vs cron traditionnel : Pas de serveur à maintenir, logs intégrés, et vos jobs sont versionnés avec votre code.
3. Vector Search Intégré
Pas besoin de Pinecone ou Qdrant pour un MVP. Convex a son propre moteur de recherche vectorielle.
1// schema.ts - Définir l'index vectoriel2export default defineSchema({3 documents: defineTable({4 content: v.string(),5 embedding: v.array(v.float64()),6 }).vectorIndex("by_embedding", {7 vectorField: "embedding",8 dimensions: 1536, // OpenAI embeddings9 filterFields: ["category"],10 }),11});1// Rechercher les documents similaires2const results = await ctx.vectorSearch("documents", "by_embedding", {3 vector: queryEmbedding,4 limit: 10,5 filter: (q) => q.eq("category", "tech"),6});flowchart LR
A[User Query] --> B[Generate Embedding]
B --> C[Vector Search]
C --> D[Top K Documents]
D --> E[LLM Context]
E --> F[AI Response]
style A fill:#FC5757,color:#fff
style C fill:#FC5757,color:#fff
style F fill:#1a1d24,stroke:#FC5757
Le plus ? La recherche est immédiatement cohérente. Contrairement aux bases vectorielles externes, pas de délai de synchronisation.
4. File Storage Sans Config
Upload, stockage, et serving de fichiers en 3 lignes de code. Pas de S3 à configurer.
1// Générer une URL d'upload (valide 1h)2const uploadUrl = await ctx.storage.generateUploadUrl();3
4// Récupérer l'URL publique d'un fichier5const fileUrl = await ctx.storage.getUrl(storageId);6
7// Supprimer un fichier8await ctx.storage.delete(storageId);Features cachées :
- Support de tous les types de fichiers
- URLs signées avec expiration
- Streaming depuis les HTTP Actions
- Métadonnées accessibles
5. HTTP Actions : Votre API REST
Convex peut exposer des endpoints HTTP pour recevoir des webhooks ou créer une API REST.
1// convex/http.ts2import { httpRouter } from "convex/server";3import { httpAction } from "./_generated/server";4
5const http = httpRouter();6
7http.route({8 path: "/webhooks/stripe",9 method: "POST",10 handler: httpAction(async (ctx, request) => {11 const body = await request.json();12 const signature = request.headers.get("stripe-signature");13 14 // Valider et traiter le webhook15 await ctx.runMutation(internal.payments.processWebhook, {16 event: body,17 });18 19 return new Response("OK", { status: 200 });20 }),21});22
23export default http;Vos endpoints sont accessibles sur https://votre-projet.convex.site/webhooks/stripe.
Use cases :
- Webhooks (Stripe, GitHub, Discord)
- API publique pour apps tierces
- Intégration avec Zapier/n8n
6. Optimistic Updates
Rendez votre UI instantanément réactive avant même que le serveur réponde.
1const addTodo = useMutation(api.todos.add).withOptimisticUpdate(2 (localStore, args) => {3 const currentTodos = localStore.getQuery(api.todos.list);4 if (currentTodos !== undefined) {5 localStore.setQuery(api.todos.list, {}, [6 ...currentTodos,7 { _id: "temp", text: args.text, completed: false },8 ]);9 }10 }11);Comment ça marche ?
sequenceDiagram
participant UI
participant LocalStore
participant Convex
UI->>LocalStore: Optimistic Update
LocalStore->>UI: UI Updated (instant)
UI->>Convex: Mutation Request
Convex->>Convex: Process Mutation
Convex->>LocalStore: Real Data
LocalStore->>UI: Reconcile (auto)
Si le serveur renvoie des données différentes, Convex rollback automatiquement l'update optimiste.
7. Internal Functions : L'Encapsulation Parfaite
Les internalQuery, internalMutation, et internalAction sont invisibles côté client. Parfait pour la logique sensible.
1// Accessible uniquement depuis le backend2export const chargeCustomer = internalMutation({3 args: { userId: v.id("users"), amount: v.number() },4 handler: async (ctx, args) => {5 // Logique de facturation sensible6 const user = await ctx.db.get(args.userId);7 await stripe.charges.create({ amount: args.amount, customer: user.stripeId });8 await ctx.db.patch(args.userId, { lastCharged: Date.now() });9 },10});11
12// Appel depuis une autre fonction13await ctx.runMutation(internal.billing.chargeCustomer, { userId, amount: 1999 });Sécurité : Ces fonctions n'apparaissent pas dans l'objet api exposé au client. Impossible de les appeler depuis le frontend.
8. Pagination Réactive
La pagination Convex est fully reactive. Quand un document change, votre page se met à jour automatiquement.
1// Backend2export const listMessages = query({3 args: { paginationOpts: paginationOptsValidator },4 handler: async (ctx, args) => {5 return await ctx.db6 .query("messages")7 .order("desc")8 .paginate(args.paginationOpts);9 },10});11
12// Frontend - Infinite scroll automatique13const { results, status, loadMore } = usePaginatedQuery(14 api.messages.list,15 {},16 { initialNumItems: 20 }17);Le trick ? Combinez avec l'Intersection Observer pour un infinite scroll parfait :
1useEffect(() => {2 const observer = new IntersectionObserver(3 ([entry]) => entry.isIntersecting && status === "CanLoadMore" && loadMore(20)4 );5 observer.observe(sentinelRef.current);6 return () => observer.disconnect();7}, [status, loadMore]);9. Components : Modules Réutilisables
Convex permet de créer des composants backend packagés comme des modules NPM.
1// Installation2npm install @convex-dev/aggregate3
4// Utilisation5import { Aggregate } from "@convex-dev/aggregate";6
7const aggregate = new Aggregate<number>(components.aggregate, {8 sortKey: (doc) => doc.createdAt,9 sumValue: (doc) => doc.amount,10});11
12// Obtenir des stats en temps réel13const stats = await aggregate.sum(ctx, { prefix: ["sales", "2026"] });Components officiels disponibles :
@convex-dev/aggregate- Agrégations temps réel@convex-dev/auth- Authentification complète@convex-dev/rate-limiter- Rate limiting@convex-dev/crons- Crons avancés
10. Validation avec Zod
Combinez la puissance de Zod avec Convex pour une validation avancée :
1import { zCustomMutation } from "convex-helpers/server/zod";2import { z } from "zod";3
4const mutation = zCustomMutation(baseMutation);5
6export const createUser = mutation({7 args: {8 email: z.string().email(),9 age: z.number().min(18).max(120),10 preferences: z.object({11 theme: z.enum(["light", "dark"]),12 notifications: z.boolean(),13 }),14 },15 handler: async (ctx, args) => {16 // args est parfaitement typé et validé17 return await ctx.db.insert("users", args);18 },19});Avantages vs validators natifs :
- Validations complexes (regex, min/max, enums)
- Messages d'erreur personnalisés
- Transformations de données
- Réutilisation des schémas
Récapitulatif
| Feature | Use Case | Impact | |---------|----------|--------| | Scheduled Functions | Emails, rappels, jobs différés | ⭐⭐⭐⭐⭐ | | Vector Search | RAG, semantic search | ⭐⭐⭐⭐⭐ | | HTTP Actions | Webhooks, API REST | ⭐⭐⭐⭐ | | Optimistic Updates | UX instantanée | ⭐⭐⭐⭐ | | File Storage | Upload/download | ⭐⭐⭐⭐ | | Components | Code réutilisable | ⭐⭐⭐ |
Leçon apprise : Convex n'est pas juste une "base de données réactive". C'est un backend complet qui remplace Supabase, Firebase, et même certains services AWS. Creusez la doc, les pépites sont partout.