Limits, pooling and zero-downtime deploys
Everything on this page is about a server with real load on it: bounding what one instance can take from the others, putting a pooler in front of the shared cluster, and replacing a container without anybody noticing.
An instance's container has limits
Under Container limits on the instance's Configuration tab:
| Mode | What it does |
|---|---|
| Auto (default) | Derives the CPU and memory limits from the workload and tuning above it: what the workers, cron threads and websocket worker are expected to hold, with a quarter on top |
| Manual | You set them, starting from what Auto derived rather than from nothing |
| Off | No limits |
The card shows what the container actually gets beside the values it was derived from, so you can see the arithmetic rather than trusting it.
Raising or lowering a limit applies without a restart. Removing one recreates the container, which costs the same seconds a restart would - and the apply tells you which of the two happened rather than leaving you to infer it from the downtime.
A CPU limit never goes above the server's CPUs. A manual CPU limit higher than the number of CPUs the server has is refused when you save it. An instance that arrives with one anyway - restored from a larger server, or on a server that was given fewer CPUs - gets its limit lowered to the server's CPUs when it starts, and the job log says so.
A storage threshold is a report, not a cap
An instance can carry a storage threshold. The Resources > Storage page shows the figure and marks what is over it, and crossing it raises the Instance storage threshold alert once, resolved when the instance is back under it.
It does not stop anything. Nothing is refused, no write fails, and the instance does not go read-only. If you want a cap, that is the filesystem's job, not this setting's.
pelmo$ ohm instance quota show --instance fanes --server pelmopelmo$ ohm instance quota set --instance fanes --server pelmoThe shared cluster
Under PostgreSQL > Local > Scaling.
Ceilings
The shared PostgreSQL container can be given a CPU and a memory ceiling, and the read replica has ceilings of its own on the Read replica card.
pelmo$ ohm server scaling show --server pelmopelmo$ ohm server scaling set --server pelmoThe connection pooler
A pooler can sit in front of the shared cluster. Turn it on under Scaling; each instance opts in on its own Configuration tab, and the ones that do not keep connecting directly - so you can move instances onto it one at a time rather than all at once.
The Scaling page and Core services show the pools, the clients on each, and the clients waiting.
No instance password is ever copied into the pooler. An instance on a named profile or an external server is refused, with the reason.
pelmo$ ohm server pgbouncer status --server pelmopelmo$ ohm server pgbouncer install --server pelmoThe read replica
A streaming copy of the shared cluster on loopback port 5433, for reporting tools and as a warm standby. The Scaling page shows whether it is streaming and how far behind it is.
| Action | What it does |
|---|---|
| Rebuild | Takes a fresh copy |
| Promote | Makes the copy a database of its own, and prints the steps that would follow |
A replica that falls more than 4 GB behind has to be rebuilt. That ceiling is
max_slot_wal_keep_size, and it is protecting the primary, not the standby: a replication slot makes
the primary keep WAL the standby has not read yet, so a standby that is stopped and forgotten is the
classic way to fill a production disk and stop the primary from writing. Past the ceiling the
slot is marked lost and the standby is the thing that breaks instead. That is the right trade, but
it means a standby you shut down "for now" is on a clock.
And a major-version migration refuses to start while a replica exists, unless you accept that it will be rebuilt. Plan the rebuild into the migration window rather than discovering it inside one.
Odoo never reads from the replica. Its ORM sends every query to the single database host it is configured with. The replica is for tools you point at it yourself - and for Analytics, which reads through it whenever one is streaming.
pelmo$ ohm server replica status --server pelmoReplacing a container without an outage
The instance's Deploy page starts a new container beside the running one, waits until it answers, switches to it, and only then removes the old one.
- A deploy that goes wrong changes nothing. The old container is still the one serving.
- An interrupted deploy offers Recover.
- The page states what the deploy costs before you start it, and is refused up front when the host has too little memory free to start a second container.
The cost is worth reading rather than skipping. With the shipped defaults the new container has 180 seconds to answer and the old one drains for 30 after the switch, so for up to 210 seconds this instance occupies its memory and CPU ceiling twice over. Both containers share the same filestore, configuration and database throughout, so the instance behaves as one - but the host has to have the headroom for two.
Those two numbers are Deploy defaults on the same page, and they apply to every instance on the server rather than to the one you are looking at.
pelmo$ ohm instance deploy status --instance fanes --server pelmopelmo$ ohm instance deploy run --instance fanes --server pelmopelmo$ ohm instance deploy recover --instance fanes --server pelmoRestarting and recreating an instance the ordinary way is never restricted; it is only the side-by-side switch that needs the edition.
Module updates get a real maintenance page
pelmo$ ohm instance deploy modules --instance fanes --server pelmoThere is no zero-downtime module update, and the page says so: Odoo runs the schema changes in the database its own workers serve, so no version of this keeps answering. What the maintenance page buys you is that the fetch and the image build happen while the instance is still serving, so visitors meet it only for the update rather than for the whole build.
A dump of the active database is taken first unless you switch it off, and its path is reported. The maintenance page tells the caller when to come back. On an instance with firewall rules, only visitors the rules let in see it; a visitor the rules refuse keeps getting the instance's refusal.