Menu

De combien de workers Odoo avez-vous vraiment besoin ? Bien dimensionner les workers et régler PostgreSQL correctement

Un guide pratique et sans détour pour calculer les workers Odoo à partir de votre CPU et de votre RAM, écrire un odoo.conf correct et régler PostgreSQL pour la façon dont Odoo fonctionne réellement
Pressé ? Allez directement au calculateur gratuit de workers Odoo & PostgreSQL en bas de page. Saisissez votre CPU et votre RAM, copiez les odoo.conf et postgresql.conf générés.

Tout administrateur Odoo finit par copier la même ligne depuis un forum : workers = (CPU x 2) + 1. Ce n'est pas faux, mais ce n'est que la moitié de l'histoire — et la moitié manquante est précisément ce qui remplit vos logs de MemoryError et de « too many connections ».

Le nombre de workers n'est pas un problème de CPU. C'est un problème de RAM avec un plafond CPU. Et une fois vos workers bien réglés, le goulot d'étranglement suivant est presque toujours PostgreSQL, qui tourne encore avec des valeurs par défaut de 2005 pour une charge qui n'a rien à voir avec Odoo. Ce guide traite les deux, avec les valeurs exactes, les calculs qui les justifient et les pièges que les articles de blog habituels passent sous silence.

Ce qu'est réellement un worker Odoo

En mode multiprocessing (le seul mode à utiliser en production), Odoo fork plusieurs processus système indépendants. Chacun charge l'environnement Python complet et tous les modules installés, puis garde cette mémoire résidente, même au repos. Il en existe trois types :

workers
Workers HTTP
Ils traitent chaque clic utilisateur, appel RPC et requête web. C'est le nombre auquel les gens pensent quand ils disent « workers ».
max_cron_threads
Workers cron
Ils exécutent les actions planifiées en arrière-plan. Ce sont des processus distincts qui consomment eux aussi de la RAM et une part de CPU.
gevent / longpolling
Worker temps réel
Un processus dédié (port 8072) pour le chat en direct, Discussion et les notifications du bus. Réservez-le toujours.

Ce que la plupart des guides oublient de dire clairement : les workers cron et gevent comptent eux aussi dans votre budget RAM. Si vous ne prévoyez que les workers HTTP, vous avez déjà sous-dimensionné la machine.

La formule que tout le monde cite, et ce qu'elle oublie

La règle bien connue vous donne un plafond, pas une réponse :

workers max théoriques = (cœurs CPU x 2) + 1

Deux autres règles empiriques aident à dimensionner d'après la demande plutôt que d'après le matériel :

  • Un worker HTTP sert confortablement environ 6 utilisateurs simultanés (des personnes qui cliquent activement, pas seulement connectées).
  • Il vous faut un minimum de 2 workers HTTP en production. La génération de PDF/rapports rappelle Odoo en HTTP via wkhtmltopdf, et avec un seul worker elle se bloque en s'attendant elle-même.
La règle qui vous garde réellement en vie : (workers + cron + gevent) x limit_memory_soft doit rester sous la RAM que vous réservez à Odoo, après avoir laissé de la place à PostgreSQL et à l'OS. Le CPU fixe le plafond ; la RAM fixe le vrai nombre. C'est le plus petit des deux qui l'emporte.

Voilà pourquoi le même « (CPU x 2) + 1 » peut être parfait sur un serveur et provoquer des OOM sur un autre. Une machine à 8 cœurs annonce « jusqu'à 17 workers », mais avec la valeur par défaut de limit_memory_soft de 2 Go, 17 workers exigeraient 34 Go de RAM pour Odoo seul.

Un odoo.conf correct, ligne par ligne

Voici un bloc prêt pour la production, avec les valeurs qui correspondent au comportement réel d'Odoo 16+. Les commentaires expliquent le rôle de chaque limite et sa vraie valeur par défaut.

/etc/odoo/odoo.conf INI
[options]
# --- Process model ---
workers              = 5      # HTTP workers (the real tuning knob)
max_cron_threads     = 1      # default is 2; raise only for heavy background jobs
proxy_mode           = True   # required when behind nginx/HAProxy

# --- Memory limits (bytes) ---
# soft = worker finishes its request, then is recycled (default 2048 MB)
# hard = worker is killed immediately            (default 2560 MB)
limit_memory_soft    = 805306368    # 768 MB
limit_memory_hard    = 1006632960   # 960 MB

# --- Time limits (seconds) ---
limit_time_cpu       = 60     # CPU time per request   (default 60)
limit_time_real      = 120    # wall-clock per request (default 120, ~2x cpu)
limit_time_real_cron = 300    # longer leash for cron jobs
limit_request        = 65536  # requests before a worker recycles (default 2^16)

# --- Database connection pool ---
db_maxconn           = 32     # max PG connections PER worker (default 64) -- see trap below
Un mythe à oublier : certains guides écrivent limit_memory_soft = 2684354560 « = 2,5 Go ». En réalité, cette valeur en octets est la valeur par défaut de limit_memory_hard. La vraie valeur par défaut de soft est 2147483648 (2 Go). Gardez toujours soft en dessous de hard, jamais égal ni au-dessus.

Le piège des connexions dont personne ne parle

Voici celui qui casse la production en charge. Chaque worker Odoo conserve son propre pool pouvant atteindre db_maxconn connexions PostgreSQL. Le plafond réel qu'Odoo peut ouvrir est donc :

connexions PG max ≈ (workers + cron + gevent) x db_maxconn

Avec les valeurs par défaut (disons 8 workers et db_maxconn = 64), cela fait plus de 500 connexions possibles, alors que PostgreSQL est livré avec max_connections = 100. Lors d'un pic de trafic, vous tombez sur FATAL: sorry, too many clients already et le site se bloque. Deux façons de corriger ça, idéalement les deux :

  • Abaissez db_maxconn à 16–32 pour que le pire des cas tienne dans le max_connections de Postgres.
  • Pour des parcs plus importants, placez PgBouncer en mode transaction devant Postgres et dimensionnez max_connections sur le pool, pas sur les workers.

Régler PostgreSQL pour la façon dont Odoo fonctionne

La charge d'Odoo est de type OLTP : un déluge de petites requêtes indexées générées par l'ORM et de transactions courtes, pas quelques gigantesques parcours analytiques. Cela conditionne chacune des valeurs ci-dessous. Elles supposent que Postgres dispose de la machine (ou d'une part connue de celle-ci) pour lui seul.

Paramètre
Valeur
Pourquoi
shared_buffers
25 % de la RAM
Le cache de pages propre à PG. Descendez à ~15 % si Postgres partage la machine avec Odoo.
effective_cache_size
50–75 % de la RAM
Une indication pour le planificateur, pas une allocation. Indique à PG quelle quantité de cache OS+PG il peut supposer, ce qui le pousse à privilégier les parcours d'index.
work_mem
16–32 MB
Par tri/hachage, par opération. À manier avec précaution ; voir l'encadré ci-dessous.
maintenance_work_mem
256 MB–1 GB
Accélère VACUUM, CREATE INDEX et les migrations. Utilisé par peu de processus à la fois, il peut donc être généreux.
random_page_cost
1.1
La valeur par défaut de 4.0 suppose des disques mécaniques. Sur SSD/NVMe, les lectures aléatoires coûtent presque aussi peu que les lectures séquentielles.
effective_io_concurrency
200
Pour du NVMe (utilisez ~64 pour un SSD SATA, 1–2 pour un disque dur). Permet à PG de précharger en parallèle.
checkpoint_completion_target
0.9
Étale les écritures de checkpoint dans le temps au lieu d'un pic d'E/S qui fige l'interface.
max_wal_size
2–4 GB
Des checkpoints moins nombreux et plus gros. À associer à min_wal_size = 1GB.
jit
off
Le JIT n'est rentable que sur de longues requêtes analytiques. Sur les nombreuses petites requêtes d'Odoo, il ne fait qu'ajouter de la surcharge.
autovacuum_vacuum_scale_factor
0.05
Odoo brasse mail.message, bus.bus, les logs. Faites le VACUUM plus tôt pour éviter le gonflement des tables.
Pourquoi nous sommes prudents sur work_mem : il est alloué par opération de tri ou de hachage, et une seule requête peut en exécuter plusieurs à la fois. Dans le pire des cas, la mémoire vaut environ connexions_actives x work_mem x opérations_par_requête. Les blogs qui recommandent 64–256 Mo supposent une configuration avec pooling et peu de connexions ; reprenez cette valeur sur un serveur Odoo à 150 connexions et un seul moment de charge peut faire swapper le serveur jusqu'à la mort. Commencez à 16–32 Mo et n'augmentez que pour des rapports lents précis, idéalement avec un SET work_mem par session.

N'oubliez pas le reverse proxy

Les workers et Postgres sont réglés, mais si le chat en direct et les notifications « ne marchent pas », c'est presque toujours le proxy. Le trafic temps réel utilise le port gevent/longpolling (8072) et doit être routé séparément des requêtes normales (8069). Voici le nginx minimal qui fait les choses correctement.

/etc/nginx/sites-available/odoo nginx
upstream odoo      { server 127.0.0.1:8069; }
upstream odoochat  { server 127.0.0.1:8072; }

server {
    listen 443 ssl;
    server_name erp.example.com;

    # real-time bus / longpolling -> gevent worker
    location /websocket          { proxy_pass http://odoochat; }
    location /longpolling        { proxy_pass http://odoochat; }

    # everything else -> HTTP workers
    location /                  { proxy_pass http://odoo; }

    proxy_set_header Host              $host;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

À associer à proxy_mode = True dans odoo.conf pour qu'Odoo fasse confiance aux en-têtes transmis. Sur Odoo 16, le canal temps réel est /websocket ; les versions plus anciennes utilisaient /longpolling, gardez donc les deux par sécurité.

Exemple concret : 4 vCPU / 8 Go, Odoo + Postgres sur une seule machine

Une configuration de départ très répandue. Dimensionnons-la honnêtement, de bout en bout.

  1. Plafond CPU : (4 x 2) + 1 = 9 workers maximum.
  2. Budget RAM : 8 Go au total − ~1 Go OS − ~2 Go PostgreSQL ≈ 5 Go pour Odoo.
  3. Workers limités par la RAM : à limit_memory_soft = 768 MB, 5 Go / 0,77 ≈ 6 processus. Réservez-en 1 pour le cron + 1 pour gevent → ~4–5 workers HTTP.
  4. Le plus petit des deux gagne : 5 (RAM) < 9 (CPU) → utilisez workers = 5, max_cron_threads = 1.
  5. Connexions : (5 + 1 + 1) x db_maxconn 32 = 224 dans le pire des cas → réglez Postgres sur max_connections = 250, ou gardez 100 et ajoutez PgBouncer.
  6. Postgres : shared_buffers = 2GB, effective_cache_size = 4GB, work_mem = 16MB, maintenance_work_mem = 256MB.

Cinq workers HTTP supportent confortablement ~30 utilisateurs simultanés sur cette machine. Besoin d'en servir 60 ? Vous êtes limité par la RAM, pas par le CPU : ajoutez de la mémoire (ou déplacez Postgres sur une autre machine) avant d'ajouter des cœurs.

Règle d'or : après le déploiement, surveillez l'usage réel et maintenez les pics CPU et RAM sous les ~80 %. C'est cette marge qui absorbe la tempête de connexions du lundi matin et la vague de facturation de fin de mois.

Passez les calculs : le calculateur de workers Odoo de DevTalents

Tout ce qui précède est intégré dans un outil gratuit. Saisissez vos cœurs CPU, votre RAM, le type de stockage et si Postgres partage la machine ; il applique le plafond de RAM, le calcul des connexions et le profil PostgreSQL OLTP, puis vous remet un odoo.conf et un postgresql.conf prêts à coller.

Générez votre config en 10 secondes

Workers, limites de mémoire, threads cron, db_maxconn et un profil PostgreSQL assorti. Copiez, collez, redémarrez.

Ouvrir le calculateur de workers →

Vous exploitez une vraie instance de production et souhaitez un deuxième avis ? Notre équipe dimensionne et règle des déploiements Odoo au quotidien, alors contactez-nous.

calculateur de workers Odoo, configuration des workers Odoo, combien de workers Odoo, formule workers Odoo, CPU x 2 + 1 Odoo, Odoo limit_memory_soft limit_memory_hard, Odoo limit_time_cpu limit_time_real, max_cron_threads Odoo, db_maxconn Odoo, exemple odoo.conf production Odoo, réglage PostgreSQL Odoo, postgresql.conf Odoo, shared_buffers work_mem effective_cache_size Odoo, corriger too many connections Odoo, PgBouncer Odoo, reverse proxy nginx Odoo longpolling websocket 8072, optimisation des performances Odoo, réglage des performances PostgreSQL Odoo, MemoryError workers Odoo, dimensionnement RAM workers multiprocessing Odoo
Partager cette publication
OWL : L'avenir du développement Odoo