In this article
Shared hosting and managed Odoo platforms work fine at small scale but develop predictable limitations as deployments grow. This article covers Odoo’s infrastructure requirements, how to size bare metal hardware for real workloads, and how OpenMetal’s private networking enables a clean app-and-database split when you need it.
There’s a predictable inflection point in Odoo deployments where two problems arrive at the same time: the per-user infrastructure cost starts to feel disproportionate, and performance gets inconsistent in ways that trace back to a database the team has no access to tune.
It usually hits somewhere between 30 and 100 named users. It arrives earlier if MRP, ecommerce, or large-scale accounting modules are running. And it tends to show up as slowdowns during batch operations and report generation, which are exactly the operations that matter most to finance and operations teams.
Dedicated bare metal addresses both sides of it. Infrastructure cost becomes fixed regardless of headcount. PostgreSQL moves to hardware the team controls and can configure properly.
What Makes Odoo Demanding on Infrastructure
Odoo is a Python application that uses PostgreSQL as its only supported database. Every action in the system, from a sales order to an inventory adjustment to a scheduled automation, generates database activity. This is different from applications that can offload reads to caches or use lighter-weight databases for parts of their stack. In Odoo, everything goes through PostgreSQL.
The application runs in multi-process mode in production, where the number of concurrent request handlers is set by the workers parameter in odoo.conf. Odoo’s documentation gives the canonical formula:
workers = (CPU cores × 2) + 1
Each worker handles one request at a time. Workers are your actual concurrency ceiling, not the CPU core count itself. Each worker consumes roughly 150 to 300 MB of RAM at rest and can spike well past 1 GB during heavy operations like inventory valuations, financial closings, or large report exports. On an undersized server, this is where performance collapses: workers exhaust available RAM, the OS starts swapping, and response times degrade from seconds to minutes.
PostgreSQL compounds this. The database performs best when its working set fits in memory, controlled by the shared_buffers setting in postgresql.conf. The standard recommendation is to allocate 25% of total system RAM to shared_buffers. On a server with 8 GB of RAM, that is 2 GB for the database buffer pool. On a server with 256 GB, it is 64 GB, which means most active tables and indexes stay in memory rather than hitting storage for every query. This is one of the most impactful single-configuration changes for Odoo performance, and it requires access to the PostgreSQL configuration file, which managed platforms like Odoo.sh do not provide.
Heavy modules change the resource math significantly. A basic CRM deployment is far lighter than one running manufacturing (MRP), ecommerce, or large-scale accounting. Adding MRP or ecommerce can roughly double the CPU and RAM requirements for the same number of concurrent users. If your deployment includes these modules, size for it from the start.
Sizing by Concurrent Users, Not Named Users
The most common Odoo sizing mistake is using the named user count rather than concurrent users. A 100-person company rarely has 100 people actively using Odoo at the same moment. A realistic estimate is 30 to 50 percent of named users being concurrent during peak hours, lower in shift-based or field-heavy operations.
For production Odoo deployments running standard modules, the working baselines are:
- Up to 25 concurrent users: 4 dedicated cores, 8 GB RAM
- 25 to 60 concurrent users: 8 dedicated cores, 16 GB RAM
- 60 to 100 concurrent users: 16 dedicated cores, 32 GB RAM (database separation recommended at this scale)
- Above 100 concurrent users: split application and database servers, scale each independently
These numbers assume standard modules. Add 50 to 100% headroom if MRP, ecommerce, or large-scale batch reporting are part of the deployment.
Storage sizing is dominated by the filestore, not the database. The Odoo filestore holds attachments, documents, product images, and other binary content. For businesses handling significant document volume, plan 2 to 5 GB of filestore growth per active user per year. The database itself grows slowly by comparison. NVMe storage handles both well: the fast random I/O that PostgreSQL needs for index lookups and the throughput that large file operations require.
Dedicated Cores vs. vCPUs for PostgreSQL
PostgreSQL is one of the workloads most sensitive to CPU contention. It relies on predictable I/O scheduling and CPU time for its vacuum processes, autovacuum, and query execution. On a shared cloud instance where vCPUs are time-sliced across tenants, autovacuum and background workers compete with your query workload for CPU time. The practical result is inconsistent query latency, especially under load.
Dedicated bare metal gives PostgreSQL exclusive access to physical cores. There is no time-sharing with neighboring tenants. The I/O scheduler services only your workload. This matters most for the operations that typically cause complaints in shared environments: large reports, inventory valuations, financial period closings, and MRP scheduling runs.
It also matters for PostgreSQL configuration. You can set shared_buffers, work_mem, effective_cache_size, and autovacuum parameters to match your actual hardware and workload. On Odoo.sh, PostgreSQL tuning is not available to customers. On a VPS with 8 GB of RAM shared with other workloads, setting shared_buffers to 25% of RAM leaves limited headroom for everything else. On a dedicated bare metal server with 256 GB of RAM, PostgreSQL can hold a large working set in memory without competing with the application layer for resources.
Single Server vs. Splitting App and Database
For most Odoo deployments up to around 60 to 75 concurrent users, running the application server and PostgreSQL on the same machine is straightforward to manage and performs well with proper tuning. Both processes have access to the full RAM pool, and there is no network overhead between the application and the database.
Past that scale, or when running heavy modules with frequent large queries, moving PostgreSQL to a dedicated server becomes worthwhile. A dedicated database server lets you size memory specifically for PostgreSQL’s working set, tune the kernel and storage scheduler for database I/O, and scale the application and database tiers independently as load grows.
On OpenMetal, separating Odoo and PostgreSQL onto two bare metal servers is straightforward. Both servers sit on the same dedicated customer VLAN, with 20 Gbps of unmetered private bandwidth between them. Application-to-database traffic stays entirely on the private network, never touching a public interface. Latency between servers on the same private network is low enough that the split adds negligible overhead while giving you independent scaling and resource control for each tier.
A practical configuration for a 75 to 150 concurrent user deployment:
- Odoo application server: Large v4 or Large v5 (32 cores, 512 GB RAM). Workers set to 65 (32 cores × 2 + 1). Application RAM handles worker memory peaks and OS overhead. Connects to the database over the private VLAN.
- PostgreSQL server: Medium v4 or Medium v5 (24 cores, 256 GB RAM).
shared_buffersset to 64 GB (25% of RAM).effective_cache_sizeset to 192 GB. The 6.4 TB NVMe on the Medium v5 handles the filestore and write-ahead log with room to grow.
Hardware That Fits Odoo Workloads
Medium v4 or Medium v5 (24 cores, 256 GB RAM, 6.4 TB NVMe) suits small to medium deployments running standard modules: up to roughly 50 to 60 concurrent users with CRM, sales, inventory, and accounting. At 24 cores, you get 49 workers by the formula, which covers that concurrency range comfortably. The 256 GB RAM gives PostgreSQL 64 GB of shared_buffers with ample headroom for workers. For a deployment that is also the PostgreSQL server, this tier handles most SMB use cases well.
Large v4 or Large v5 (32 cores, 512 GB RAM, 12.8 TB NVMe) fits medium deployments running heavier modules, or serves as the application server in a split configuration. At 32 cores you get 65 workers. The 512 GB RAM supports both a well-configured PostgreSQL instance and the worker memory footprint of a larger Odoo deployment without contention. The 12.8 TB NVMe handles even document-heavy filestorage growth for years without requiring additional storage.
XL v4 or XL v5 (64 cores, 1 TB RAM, 25.6 TB NVMe) fits large deployments or serves as a dedicated PostgreSQL server for high-concurrency environments. As a PostgreSQL host, 1 TB of RAM allows a 256 GB shared_buffers allocation, which can hold a substantial working set for large databases entirely in memory. This configuration is appropriate for deployments running MRP at scale, multi-company environments with large transaction volumes, or organizations that want significant headroom before needing to scale out.
Current v5 hardware is available in Ashburn and Los Angeles. v4 is available across all locations: Los Angeles, Ashburn, Amsterdam, and Singapore. Full specs are on the hardware details page.
Who This Fits
Growing SMBs and mid-market companies running Odoo Enterprise
The per-user licensing cost of Odoo Enterprise is fixed regardless of infrastructure. Moving infrastructure to dedicated bare metal separates the licensing cost from the infrastructure cost and makes the latter predictable and fixed.
Teams running MRP, ecommerce, or large-scale accounting modules
These modules generate heavy database activity. Dedicated hardware and a tunable PostgreSQL instance are the practical path to reliable performance at this level of usage.
Companies that have outgrown Odoo.sh or VPS hosting
Odoo.sh is a well-designed managed platform with a real limitation: you cannot tune PostgreSQL. If your performance issues trace back to the database layer and you need to change shared_buffers, work_mem, or autovacuum behavior, you need infrastructure you control.
Odoo Community deployments at scale
Odoo Community is open source with no per-user license cost. At higher user counts, the only cost is infrastructure. Dedicated bare metal at a fixed monthly rate is the natural fit for community deployments that have grown beyond shared hosting.
Who This Doesn’t Fit
Small deployments with light module usage
If you have 10 to 15 users running basic CRM and sales, a VPS or Odoo.sh handles this well and the operational simplicity is worth the tradeoff. Bare metal becomes worthwhile when you are outgrowing those environments.
Teams without Linux administration experience
Running Odoo on bare metal means owning the OS, PostgreSQL configuration, Nginx setup, SSL, backups, and updates. This is standard Linux sysadmin work, but if your team does not have that capacity, a managed Odoo hosting provider is a more practical choice.
Deployments that need Odoo.sh-specific features
Odoo.sh provides built-in staging environments, one-click branch deployments, and tight integration with Odoo’s update infrastructure. If those features are central to your development workflow, a self-hosted deployment requires replicating that workflow yourself.
Frequently Asked Questions
Why does Odoo require PostgreSQL specifically?
Odoo’s ORM and all of its modules are built to PostgreSQL’s feature set, including specific data types, full-text search capabilities, and transactional behavior. There is no support for MySQL, MariaDB, or other databases. PostgreSQL is a hard dependency.
How many Odoo workers should I configure?
Odoo’s deployment documentation gives the formula: workers = (CPU cores × 2) + 1. Each worker handles one request at a time and consumes 150 to 300 MB of RAM at rest. Size your total RAM to handle the expected number of workers at peak, with headroom for PostgreSQL’s shared_buffers allocation.
How much RAM should PostgreSQL receive?
The standard recommendation is to set PostgreSQL’s shared_buffers to 25% of total system RAM. On a server with 256 GB of RAM, that is 64 GB. effective_cache_size is typically set to 75% of RAM as a hint to the query planner. These values require access to postgresql.conf, which is why managed platforms that restrict database configuration can limit performance at scale.
When should I move PostgreSQL to a separate server?
As a rough guide, splitting the application and database servers becomes worthwhile somewhere past 60 to 75 concurrent users, or earlier if heavy modules like MRP generate large batch queries that saturate the database layer. On OpenMetal, both servers connect over a 20 Gbps unmetered private network, so the inter-server latency is low and the bandwidth is not a bottleneck.
Does Odoo Community work the same way on bare metal as Odoo Enterprise?
From an infrastructure standpoint, yes. Both editions run on the same Python/PostgreSQL/Nginx stack and use the same worker model and configuration files. The difference is that Enterprise requires a valid subscription and includes additional modules not in Community. Infrastructure sizing and tuning applies equally to both.
Can I run Odoo alongside other workloads on the same bare metal server?
Yes. A common configuration is running Odoo alongside a reverse proxy, a mail server, or other internal services on the same host, particularly on larger servers where resources are not fully consumed by Odoo. The main constraint is ensuring PostgreSQL has the RAM allocation it needs without contention from other memory-intensive processes.
Can I use Ceph storage with Odoo?
Odoo’s filestore is a filesystem-based directory. A Ceph-backed volume presented as a block device and formatted with a standard filesystem works as a filestore location. This becomes relevant in multi-server configurations where the filestore needs to be accessible from multiple application nodes, or in deployments that want the data redundancy Ceph provides.
At the point where Odoo’s infrastructure cost and performance have become constraints, dedicated bare metal changes both. Infrastructure cost becomes fixed. PostgreSQL becomes fully tunable. The hardware is sized for your actual workload rather than a shared-resource approximation of it.
To scope a configuration for your Odoo deployment, talk to the team or apply for a proof of concept.
Schedule a Consultation
Get a deeper assessment and discuss your unique requirements.
Read More on the OpenMetal Blog

































