What a 503 Actually Means
A 503 Service Unavailable from an Odoo server means nginx (or your load balancer) successfully received your request but could not forward it to a running Odoo backend. The web server is alive; Odoo is not — or not reachable. Understanding that distinction is what makes this error fast to fix.
Common Root Causes
- Odoo process is not running — crashed, OOM-killed, or never started.
- Port conflict — another process is already bound to port 8069.
- nginx upstream misconfiguration — wrong host or port in the proxy_pass directive.
- Out-of-memory (OOM) kill — the Linux kernel killed Odoo workers to reclaim RAM.
- File descriptor / worker limit hit — all workers are saturated and nginx gives up.
Step 1 — Check Whether Odoo Is Running
# Systemd
sudo systemctl status odoo
# Docker
docker ps | grep odoo
docker logs --tail 100 odoo_container_name
# Bare metal
ps aux | grep odoo-bin
If the process is absent, that is your answer. Move to Step 3 to start it. If it is listed but the 503 persists, continue to Step 2.
Step 2 — Confirm Odoo Is Listening on the Expected Port
ss -tlnp | grep 8069
# or
curl -I http://127.0.0.1:8069/web/health
A healthy Odoo instance returns 200 OK from /web/health. If you get "Connection refused", Odoo is not listening — even if the process shows as running (it may still be initialising).
Step 3 — Start or Restart Odoo
# Systemd
sudo systemctl restart odoo
sudo journalctl -u odoo -n 100 --no-pager
# Docker Compose
docker compose restart odoo
docker compose logs --tail 100 odoo
Watch the logs for database connection errors or module import failures — those are the most common reasons Odoo refuses to start after a crash.
Step 4 — Check for OOM Kills
dmesg | grep -i "oom\|killed process" | tail -20
sudo journalctl -k | grep -i oom | tail -20
If you see lines like Out of memory: Kill process … (python3), your server does not have enough RAM for the number of workers configured. Either reduce workers in odoo.conf or upgrade your server. A minimum of 512 MB per worker is a safe baseline; 1 GB is recommended for production.
Step 5 — Verify nginx proxy_pass
grep -n proxy_pass /etc/nginx/sites-enabled/odoo
The directive should point to wherever Odoo actually listens:
proxy_pass http://127.0.0.1:8069;
If you moved Odoo to a Docker network, the upstream address may be the container name or a Docker bridge IP, not 127.0.0.1. After any change, reload nginx:
sudo nginx -t && sudo systemctl reload nginx
Step 6 — Check for Port Conflicts
sudo lsof -i :8069
If a non-Odoo process is bound to 8069, either stop it or change Odoo's xmlrpc_port in odoo.conf and update your nginx upstream accordingly.
Step 7 — Increase Worker / File-Descriptor Limits
Under heavy load, all Odoo workers can be saturated simultaneously. nginx will then return 502 or 503. Check:
# Current worker count in odoo.conf
grep workers /etc/odoo/odoo.conf
# Number of active connections hitting Odoo
ss -tp | grep :8069 | wc -l
See Configure Odoo Workers for the correct formula. Also ensure the OS file-descriptor limit is high enough:
# /etc/security/limits.conf or systemd service override
odoo soft nofile 65536
odoo hard nofile 65536
How DeployMonkey Prevents 503 Errors
DeployMonkey's managed hosting automatically monitors each Odoo container's health endpoint every 30 seconds. If the container fails two consecutive checks, it is restarted automatically and the team is notified. Resource limits are sized to each plan — you will not silently run out of RAM. Every plan includes Docker-based isolation, so a crashing module in one instance cannot affect others.
Get started free at deploymonkey.app — no credit card required.
Frequently Asked Questions
Why does Odoo return 503 only under heavy load?
All Odoo workers are busy. nginx waits for a free slot and gives up if none becomes available within proxy_read_timeout. Increase worker count or upgrade hardware. See scaling Odoo for 100+ users.
Odoo is running but I still get 503 — why?
The process exists but is not yet listening (still loading modules) or is listening on a different port than nginx expects. Use curl http://127.0.0.1:8069/web/health to confirm.
How do I stop Odoo from being OOM-killed?
Reduce workers in odoo.conf, add swap space as a buffer, or upgrade RAM. Setting limit_memory_soft and limit_memory_hard in odoo.conf lets Odoo recycle workers before the OS steps in.
Does restarting Odoo lose data?
No. All data lives in PostgreSQL. Restarting the Odoo application process is safe at any time.
How long does Odoo take to start?
On a typical server with 30–50 modules, 20–60 seconds. Large installations with many third-party modules can take 2–3 minutes. Do not send traffic until /web/health returns 200.