本文目前仅提供英文版本。翻译即将推出。
属于我们的Performance & Scalability系列
阅读完整指南Odoo 19 Performance Benchmarks: PostgreSQL 17 Tuning (Real Numbers)
Performance discussions about Odoo tend to drift into vague claims ("Odoo 19 is faster"). This article gives you actual benchmark numbers from production-grade hardware running Odoo 17 vs 19 with identical workloads, plus the PostgreSQL 17 tuning that delivers the largest gains. We'll cover web client latency, ORM throughput, scheduler runtime, and the worker/connection-pool thresholds that determine how many users your instance can support.
ECOSIRE runs Odoo 19 on AWS EC2 t3.xlarge for ECOSIRE.COM and has tuned production for 30+ client deployments ranging from t3.medium to c6i.4xlarge. The numbers below are from those production runs.
Key Takeaways
- List-view rendering is 40-60% faster in Odoo 19 vs 17 for typical 80-record-per-page lists
- ORM bulk operations (
create(),write()on large recordsets) gained 25-40% throughput- MRP scheduler is 3-5x faster on databases with 100+ open MOs (covered in earlier post)
- PostgreSQL 17's incremental sort and improved JSON path filters help analytics queries
- Worker process count formula:
2 * vCPU + 1for cron, separate count for HTTP- Connection pool sizing: keep PG
max_connectionsat 200, use PgBouncer for >10 workers- Filestore on local SSD beats NFS for response time but loses HA — pick based on your priority
Hardware baseline
All benchmarks below ran on:
- AWS EC2 t3.xlarge: 4 vCPU, 16 GB RAM
- Ubuntu 24.04 LTS
- PostgreSQL 17 on the same instance (production sizing — at scale, separate the DB)
- 100 GB gp3 EBS for database
- 50 GB gp3 EBS for filestore
- Ubuntu kernel default tuning + the changes documented later in this article
For the Odoo 17 baseline, we ran on Odoo 17.0+e with PG 14 (the recommended pairing at the time of 17 release).
Web client benchmarks
Synthetic load generated by Playwright with 50 concurrent users navigating typical workflows (open list, search, drill into form, edit, save).
| Workflow | Odoo 17 (PG14) | Odoo 19 (PG17) | Delta |
|---|---|---|---|
| Sales orders list (1000 records, 80/page) | 1180 ms | 510 ms | -57% |
| CRM pipeline kanban (300 cards) | 980 ms | 620 ms | -37% |
| Invoice form with 50 lines | 720 ms | 410 ms | -43% |
| Stock picking form with 200 moves | 1340 ms | 760 ms | -43% |
| Manufacturing MO form (full BOM tree) | 920 ms | 580 ms | -37% |
| Project Gantt (200 tasks) | 1850 ms | 1100 ms | -41% |
The asset-bundle split (covered in the Odoo 19 website article) drives part of the gain. The OWL refactor of stock components handles the rest.
ORM throughput
Bulk operations measured via Python script invoking ORM methods directly:
import time
products = self.env['product.template'].search([]) # ~5000 products
start = time.time()
for p in products:
p.write({'description': p.description + ' [tagged]'})
elapsed = time.time() - start
# Records per second
| Operation | Odoo 17 | Odoo 19 | Delta |
|---|---|---|---|
write() 5000 records, single field | 280 rec/sec | 410 rec/sec | +46% |
create() 5000 invoice lines | 195 rec/sec | 290 rec/sec | +49% |
read() 10000 records, 5 fields | 1680 rec/sec | 1980 rec/sec | +18% |
search() complex domain on 100K records | 540 ms | 380 ms | -30% |
| Computed-field recompute, 5000 records | 22 sec | 14 sec | -36% |
The big create/write gains come from improved batch SQL emission in 19's ORM and PostgreSQL 17's better COPY-based ingestion.
PostgreSQL 17 tuning
PG ships with conservative defaults. For Odoo 19 on a 16 GB / 4 vCPU box, the following postgresql.conf values produce noticeably better performance:
# Memory
shared_buffers = 4GB # 25% of RAM
effective_cache_size = 12GB # 75% of RAM
work_mem = 32MB # for sort/hash
maintenance_work_mem = 1GB # for vacuum/index
huge_pages = try
# Write-ahead log
wal_buffers = 16MB
max_wal_size = 4GB
min_wal_size = 1GB
checkpoint_completion_target = 0.9
# Query planner
random_page_cost = 1.1 # SSD; default 4.0 assumes spinning disk
effective_io_concurrency = 200 # SSD parallelism
default_statistics_target = 100
# Parallelism
max_worker_processes = 4 # = vCPU count
max_parallel_workers = 4
max_parallel_workers_per_gather = 2
# Connections
max_connections = 200
After applying:
- Restart PostgreSQL (most settings need restart)
- Run
ANALYZEon the database - Monitor with
pg_stat_statements
Compared to defaults, this configuration delivered ~25-35% faster query response on our workloads.
Worker process count
Odoo runs as multiple worker processes. The right count balances concurrency against memory:
- HTTP workers: handle web requests
- Cron workers: handle scheduled jobs
- Live chat / longpolling worker: separate process for long-lived connections
Formula:
- HTTP workers =
(2 * vCPU) + 1for typical mid-traffic ERP usage - Cron workers =
1-2, more if heavy automation - Total memory budget: each worker uses 200-500 MB depending on loaded modules
For our t3.xlarge (4 vCPU, 16 GB):
- 9 HTTP workers (2 × 4 + 1)
- 2 cron workers
- 1 longpolling worker
- = ~6 GB worker memory + 4 GB shared_buffers + system overhead = comfortable
If you push HTTP workers higher than 2 × vCPU + 1, you start incurring context-switch overhead that reduces per-request throughput.
Connection pooling
Odoo opens a PostgreSQL connection per worker per database. With 9 HTTP + 2 cron workers, 1 database = 11 connections. Multi-database deployments multiply this.
For 1 database + ≤12 workers, direct connection works fine. For multi-database or >12 workers, use PgBouncer in transaction-pooling mode:
# pgbouncer.ini snippet
[databases]
* = host=127.0.0.1 port=5432
[pgbouncer]
pool_mode = transaction
max_client_conn = 200
default_pool_size = 25
reserve_pool_size = 10
server_reset_query = DISCARD ALL
Note: PgBouncer in transaction-pooling mode does NOT support Odoo's prepared-statement caching. Either disable Odoo's prepared statements or use session-pooling mode (with proportional connection scaling).
Filestore considerations
Odoo's filestore (binary attachments) lives at /var/lib/odoo/filestore/<dbname>/. Two options:
- Local SSD: lowest latency, no HA. Good for single-node deployments.
- NFS / EFS: HA-friendly, higher latency. Necessary for multi-node clusters.
- S3-backed via custom module: scalable, slowest first-byte. Use for read-heavy attachments only.
In our benchmarks:
- Local SSD attachment read: 2-5 ms
- NFS attachment read: 15-40 ms
- S3 attachment read: 80-200 ms (network-dependent)
For ECOSIRE.COM we use local SSD (single-node). For multi-region clients we've used EFS with read caching.
Scaling thresholds
Approximate user counts our setups support per instance size (mixed-workload, 70% read 30% write):
| Instance | RAM | vCPU | Concurrent active users |
|---|---|---|---|
| t3.medium | 4 GB | 2 | 5-10 |
| t3.large | 8 GB | 2 | 15-25 |
| t3.xlarge | 16 GB | 4 | 40-70 |
| c6i.2xlarge | 16 GB | 8 | 80-150 |
| c6i.4xlarge | 32 GB | 16 | 200-400 |
| Multi-node + RDS | varies | varies | 500+ |
"Concurrent active" means users with the browser open and clicking; total registered users can be 5-10x this since most users aren't actively clicking at any instant.
What still slows down Odoo 19
Despite the gains, certain patterns still cost performance:
- Computed Studio fields (sandbox slower than native — see Studio article)
- Unindexed
search()on JSON fields with deep paths - Many2many fields with thousands of relations on a single record
- Reports that aggregate millions of rows without proper aggregation domains
- Bulk
write()triggering computed-field recompute on related records
Profile with --log-level=debug_sql to find the slow queries; use the developer-mode profiler for ORM-level analysis.
Frequently Asked Questions
Should I run PostgreSQL on the same server as Odoo?
For instances up to t3.xlarge / c6i.2xlarge, yes — co-location reduces network latency and is operationally simpler. Beyond that, separate the DB onto RDS or a dedicated PG server. The threshold is roughly when you have 100+ concurrent users or your DB approaches 50 GB.
Does upgrading from PG 14 to PG 17 require a separate migration?
Yes. PG major-version upgrades use pg_upgrade which is fast (minutes for typical Odoo databases) but is its own operation. Schedule it as part of the Odoo 17 → 19 migration window, not before or after. Test on staging first.
How do I monitor Odoo performance in production?
Three tools we use: (1) pg_stat_statements for slow queries, (2) Odoo's built-in profiler in developer mode, (3) external APM (Datadog or Sentry's performance product) for end-user latency. PM2 logs and htop cover process-level health.
What's the impact of Odoo's worker memory leak (rumored)?
Odoo 19 fixed several long-running memory issues from 17. Workers should plateau around 400-600 MB with normal usage. If you see workers grow beyond 1 GB, you likely have a custom module leaking — review for cached recordsets, unclosed file handles, or unbounded loops over search([]).
Can I run Odoo 19 on PostgreSQL 16 instead of 17?
Yes — PG 16 is the minimum supported. PG 17 gives ~5-10% additional gain on analytics queries due to incremental sort and improved JSON paths. For most workloads PG 16 is fine; the real reason to be on PG 17 is long-term support runway.
Performance tuning in Odoo 19 is high-leverage: a half-day of tuning can turn a sluggish instance into a snappy one. ECOSIRE's Odoo support and maintenance service includes a quarterly performance review with PostgreSQL tuning, worker rebalancing, and slow-query analysis. See our Odoo customization service for instance-specific optimization or browse our Odoo modules catalog for performance monitoring add-ons.
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
如何将自定义按钮添加到 Odoo 表单视图 (2026)
将自定义操作按钮添加到 Odoo 19 表单视图:Python 操作方法、视图继承、条件可见性、确认对话框。经过生产测试。
如何在没有 Studio 的情况下在 Odoo 中添加自定义字段 (2026)
通过 Odoo 19 中的自定义模块添加自定义字段:模型继承、视图扩展、计算字段、存储/非存储决策。代码优先,版本控制。
如何使用外部布局在 Odoo 中添加自定义报告
使用 web.external_layout 在 Odoo 19 中构建品牌 PDF 报告:QWeb 模板、paperformat、操作绑定。带有印刷徽标+页脚覆盖。
更多来自Performance & Scalability
Odoo 19 HR:技能矩阵、职业规划、绩效周期
Odoo 19 HR 升级:本地技能矩阵、职业道路规划、绩效评估周期、9 框网格、继任计划、HRIS 集成。
OpenClaw 大规模成本优化和代币效率
OpenClaw 令牌成本优化:提示缓存、模型路由、响应缓存、批处理 API 和生产代理的每租户成本护栏。
Power BI 增量刷新超过 1000 万行的表
适用于 10M 以上行表的 Power BI 增量刷新手册:分区设计、RangeStart/RangeEnd、刷新策略、查询折叠和 DirectQuery 混合。
Webhook 调试和监控:完整的故障排除指南
通过这份涵盖故障模式、调试工具、重试策略、监控仪表板和安全最佳实践的完整指南掌握 Webhook 调试。
k6 负载测试:在发布之前对您的 API 进行压力测试
掌握 Node.js API 的 k6 负载测试。涵盖虚拟用户启动、阈值、场景、HTTP/2、WebSocket 测试、Grafana 仪表板和 CI 集成模式。
Nginx 生产配置:SSL、缓存和安全性
Nginx 生产配置指南:SSL 终止、HTTP/2、缓存标头、安全标头、速率限制、反向代理设置和 Cloudflare 集成模式。