Hay errores que no se ven en staging, pero en producción te cuestan horas (o clientes). Este post es una lista directa: qué no hacer, por qué duele, y qué hacer en su lugar.
1) Exponer Odoo directo a Internet (sin proxy, sin TLS)
Error: abrir 8069/8072 al mundo “porque es más rápido”.
Impacto: credenciales y sesión viajan sin protección si no tienes HTTPS, además de ataques de fuerza bruta y enumeración.
✅ En su lugar:
Nginx/HAProxy en 443 con TLS
Odoo solo en 127.0.0.1 o red privada
proxy_mode = True
2) No rutear /websocket/ al gevent_port
Error: proxy manda todo al 8069 y te olvidas del WebSocket.
Impacto: chat/discuss/notificaciones “mueren” o se vuelven inestables.
✅ En su lugar:
/ → 8069
/websocket/ → 8072 (gevent_port)
headers correctos (Upgrade, Connection, X-Forwarded-*)
3) Usar PgBouncer pool_mode=transaction y esperar que todo lo “de sesión” funcione
Error: creer que transaction pooling sirve para cualquier cosa.
Impacto: LISTEN/NOTIFY y comportamientos de sesión se vuelven raros (tiempo real inconsistente).
✅ En su lugar:
Transaction pooling para el ORM normal
Para lo que requiera sesión persistente: bypass controlado o pool dedicado en session
4) Inflar max_connections en PostgreSQL como “solución”
Error: “subamos max_connections y listo”.
Impacto: más conexiones no siempre es más rendimiento; muchas veces es más contención, más RAM, más overhead.
✅ En su lugar:
Controla concurrencia con PgBouncer (default_pool_size)
Usa reserve_pool_size para picos cortos
Optimiza queries/índices si Postgres está al límite
5) Poner default_pool_size “a ojo” (o enorme)
Error: default_pool_size = 500 porque “tenemos muchos usuarios”.
Impacto: Postgres puede colapsar por demasiadas consultas simultáneas, y tu p99 se dispara.
✅ En su lugar:
Empieza conservador (20–80 por pool típico)
Mide SHOW POOLS; (cl_waiting, maxwait)
Ajusta según colas y salud de Postgres
6) Ignorar crons: son tus usuarios más agresivos
Error: max_cron_threads alto + crons pesados sin batching.
Impacto: transacciones largas, locks, colas en PgBouncer, lentitud “por oleadas”.
✅ En su lugar:
max_cron_threads 1–2 al inicio
Batching (lotes) en trabajos masivos
Separar horarios de crons pesados
7) No monitorear SHOW POOLS; (y enterarte por WhatsApp)
Error: tener métricas de CPU/RAM pero no mirar cola de PgBouncer.
Impacto: la saturación aparece primero como cl_waiting y maxwait, mucho antes de que se caiga algo.
✅ En su lugar:
Alertas:
cl_waiting > 0 sostenido
maxwait creciendo
Correlaciona con transacciones largas en Postgres
8) Dejar logs inútiles o inexistentes
Error: sin logs, o con verbose alto siempre.
Impacto: o no sabes qué pasó, o te ahogas en ruido.
✅ En su lugar:
PgBouncer: log_pooler_errors=1, log_connections=1, log_disconnections=1
verbose solo en incidentes (ventana corta)
rotación de logs (logrotate/journald)
9) auth_file inseguro (o sin procedimiento de rotación)
Error: userlist.txt con permisos abiertos o sin control de cambios.
Impacto: fuga de credenciales = acceso a DB.
✅ En su lugar:
permisos 0600, owner correcto
secretos fuera del repo
procedimiento de rotación + RELOAD probado
10) TLS mal entendido: require no evita MITM
Error: activar TLS “a medias” y creer que ya estás protegido.
Impacto: cifrado sin verificación puede no proteger contra MITM (depende del modo).
✅ En su lugar:
Si realmente importa: verify-full con CA/hostname correcto
Si es red confiable interna: evalúa costo/beneficio, pero documenta la decisión
11) No probar restore (tener backups “decorativos”)
Error: “tenemos backups” sin test de restore.
Impacto: el día que lo necesitas, descubres que no sirve.
✅ En su lugar:
restore probado en staging
RTO/RPO real medido
automatización + verificación
12) Mezclar cambios de performance con cambios funcionales
Error: al mismo tiempo que pones PgBouncer, cambias módulos, haces upgrade y tocas infraestructura.
Impacto: cuando algo falla no sabes qué lo causó.
✅ En su lugar:
cambios por etapas:
proxy/websocket
PgBouncer + pool sizing
tuning y optimización
medición antes vs después (p95/p99, conexiones, RAM)
Cierre: el “error raíz” es operar sin señales
La mayoría de los problemas no son “bugs”: son configuración sin límites y sin observabilidad.
Si solo te llevas 3 cosas:
/websocket/ bien ruteado
SHOW POOLS; con alertas (cl_waiting, maxwait)
crons cortos y en lotes (sin transacciones eternas)