Odoo best practices
Odoo is a Python ERP that runs as its own long-lived service behind an Nginx reverse proxy. Getting good, stable performance is mostly about right-sizing the worker pool, keeping PostgreSQL healthy, and letting Nginx serve static and filestore content. This page covers what TurboStack already configures for you and the optimizations worth applying on top.
What TurboStack configures for you
When you set app_type: odoo, the platform provisions a complete, tuned Odoo stack:
- A dedicated systemd service that launches
odoo-binfrom your pyenv-managed Python and restarts automatically on failure (Restart=on-failure). - An Nginx reverse proxy with
proxy_mode = Trueset in Odoo, forwardingX-Forwarded-*andX-Real-IPheaders so Odoo sees the correct client address and scheme. - Multiprocess workers, auto-calculated from the server's CPUs, plus
max_cron_threads = 2for scheduled jobs. - A separate websocket/longpolling endpoint - Nginx routes
/websocket(Odoo 16+) and/longpolling(Odoo 15 and earlier) to the gevent port (8072by default). Normal traffic goes to the main port (8069). - Per-worker resource limits:
limit_memory_soft(2 GB),limit_memory_hard(4 GB),limit_time_cpu(3600 s),limit_time_real(7200 s) andlimit_request(8192). - Direct filestore delivery:
x_sendfile = Trueplus an Nginxinternal/web/filestorelocation, so attachments are streamed by Nginx instead of through Python workers. - A PostgreSQL connection with a dedicated role and database, plus a generated
admin_passwdfor the database manager. - A ready-made
odoo.conf.samplein yourconf/directory with all of the above as a starting point.
Note
An Odoo deployment uses PostgreSQL only. There is no PHP, no MySQL/MariaDB, and no Varnish layer.
Recommended optimizations
- Tune the worker count to your workload. The default scales with CPUs. Odoo's guideline is roughly
(2 x CPU) + 1HTTP workers, or about one worker per 6 concurrent users - use the lower of the two. More workers serve more concurrent users but cost RAM - seeSizing and scaling . - Keep filestore on disk, not in the database. The platform already serves it via Nginx; avoid storing attachments in PostgreSQL, which bloats the database and backups.
- Run Odoo in production mode. Do not enable
dev_modeordemodata on a live site; the defaults already disable them (without_demo = True). - Pre-compile and cache assets. Let Odoo bundle and minify JS/CSS (the default), and serve them through Nginx with long cache headers.
- Right-size cron threads. Heavy scheduled actions (mailings, accounting, inventory valuation) run under
max_cron_threads; keep them modest so cron jobs do not starve HTTP workers. - Tighten timeouts for long operations. Imports and reports may need higher
limit_time_real/limit_time_cpu; raise them deliberately rather than disabling them. - Front it with HTTP caching/Content Delivery Network (CDN) where safe. Static assets and public application pages cache well; never cache authenticated
/websession traffic. - Install Python dependencies in the virtual environment. Use the project's pip, never system-wide:
pip install -r odoo/requirements.txtfor core, andpip install -r custom-addons/<addon>/requirements.txtper add-on. - Leave
db_maxconnat its default (64). The platform's PostgreSQL is tuned for high concurrency; raising it rarely helps and can exhaust connections.
Manage the Odoo and PostgreSQL services from the host Services tab.
Sizing and scaling
The worker pool and memory limits are auto-tuned from the server's resources, and PostgreSQL is sized by the platform. Override defaults only with measured evidence:
Tip
Each Odoo worker can consume up to ~2-4 GB. Add workers only if free memory comfortably absorbs the extra processes, or you risk swapping and Out Of Memory (OOM) kills.
See Performance tuning for the general approach to changing auto-tuned values.
Stability
- Back up regularly. Ensure both PostgreSQL and the filestore are covered - see Backups. A database backup without the matching filestore loses attachments.
- Watch the Health tab for CPU, memory, and service status; rising memory or worker restarts are early warnings.
- Keep Odoo and modules current. Apply security and point releases, and review third-party modules before upgrading major versions.
- Test on a staging clone. Validate module installs/upgrades (
-u) and configuration changes on a copy before touching production.