Architecture backend pour éviter les délais d'attente de 60 secondes et les plantages d'UI avec les LLM économiques
Utiliser des modèles économiques comme DeepSeek Chat, GPT-4o-mini ou Gemini 2.5 Flash permet de réduire considérablement les coûts d'API. Le problème, c'est que dès qu'il y a un peu de trafic, les temps de réponse grimpent en flèche, passant de 10 à 60 secondes. Dans une structure de requêtes HTTP synchrones classique, ce type de latence bloque les processus de workers du serveur, les rendant inactifs, tandis que le front-end finit par planter en renvoyant une erreur de délai d'attente (timeout).
Pour un développeur solo qui gère un projet secondaire ou qui dispose d'un budget serré, la paralysie du serveur est fatale. Pourtant, impossible de repasser sur des modèles plus coûteux. Il faut donc concevoir soi-même une architecture de découplage asynchrone qui coupe la connexion synchrone directe entre le client et le LLM, tout en transmettant en toute sécurité les sorties parfois erratiques du modèle vers le front-end.
Mise en place d'une file d'attente d'arrière-plan asynchrone basée sur Celery et Redis
Il ne faut jamais laisser le serveur web attendre directement la fin de l'inférence du LLM. Il est nécessaire d'utiliser FastAPI comme passerelle API, en combinant un broker de messages Redis et des workers distribués Celery pour dissocier complètement la réception des requêtes et le calcul d'inférence proprement dit. Lorsqu'un utilisateur envoie une requête, le serveur renvoie immédiatement l'ID de la tâche et coupe la connexion.
Si vous lancez Celery avec sa configuration par défaut, les tâches risquent d'être perdues ou exécutées en double en cas de plantage d'un worker. Pour encaisser des temps de traitement qui s'allongent en raison de la nature des LLM, il faut augmenter visibility_timeout à 3600 secondes et définir task_acks_late = True pour n'envoyer un accusé de réception qu'au moment où la tâche se termine normalement. Il est également indispensable de configurer worker_prefetch_multiplier = 1 afin qu'un seul worker ne s'accapare pas plusieurs tâches lourdes en créant un goulet d'étranglement.