El problema de SQLite en Render y cómo PostgreSQL lo soluciona 💾
Una guía visual sobre por qué perdías tus datos en Render y cómo PostgreSQL garantiza su persistencia
¿Por qué desaparecían tus datos?
SQLite guarda los datos en un archivo dentro del contenedor. En Render, los contenedores son efímeros - se destruyen con cada actualización.
Contenedor reinicia = Datos perdidos
Render recrea los contenedores frecuentemente: por actualizaciones, cambios de configuración, o simplemente por mantenimiento del servicio.
Cada reinicio = SQLite se borra
1. Despliegas n8n con SQLite en Render
2. Creas workflows y guardas credenciales
3. Render reinicia el contenedor (actualización, mantenimiento, etc.)
4. Todo desaparece - el archivo SQLite se destruye
5. Vuelves a empezar desde cero 😢
El crimen de la "Memoria de Pez" en Render
Render (y muchos servicios cloud) tratan a los contenedores como efímeros. Piensa en ellos como habitaciones de hotel.
Es un archivo (database.sqlite)
que vive dentro de esa habitación.
Cuando Render hace un "re-deploy" (actualización o reinicio), es como si hiciera el checkout del hotel y quemara la habitación. Todo lo que estaba adentro (el archivo SQLite con sus flujos y ejecuciones) se destruye. Se crea una habitación nueva, limpia y vacía.
En lugar de guardar los datos dentro de la habitación (contenedor), contratamos una caja fuerte externa blindada.
n8n (la aplicación) se conecta por un "cable" (red interna) a esta caja fuerte.
Si n8n se reinicia, se actualiza o explota, no importa. Al volver a encenderse, se conecta a la caja fuerte y ahí está todo.
Esta variable es la llave de la caja fuerte. Si reinstalan todo pero pierden esta clave, perderán el acceso a todas las credenciales (APIs, contraseñas) guardadas en n8n, aunque tengan la base de datos.
¡Guárdenla como oro!
Persistencia garantizada, sin importar cuántas veces reinicie
PostgreSQL guarda tus datos fuera del contenedor de n8n, ya sea en un volumen Docker persistente o como servicio independiente en Render. Tus datos sobreviven a cualquier reinicio.
Usando docker-compose, PostgreSQL corre en un contenedor separado con volúmenes persistentes. Los datos se guardan en el disco físico de tu servidor.
Render ofrece PostgreSQL como servicio completamente independiente. n8n se conecta a esta base de datos externa y tus datos están siempre seguros.
Cómo se separan las "cajas" (servicios) para proteger tu información
graph TD
subgraph SERVER ["Servidor / Docker Host"]
style SERVER fill:#f9f9f9,stroke:#333,stroke-width:2px
subgraph NETWORK ["Red Interna Privada"]
style NETWORK fill:#e1f5fe,stroke:#0277bd,stroke-dasharray: 5 5
N8N[("🚀 Contenedor n8n
(Procesamiento / Stateless)")]
PG[("🐘 Contenedor PostgreSQL
(Base de Datos / Stateful)")]
end
DISK[("💾 Disco Físico del Servidor
(Volumen Docker)")]
N8N -- "Lee/Escribe Datos (Puerto 5432)" --> PG
PG -- "Guarda Datos Permanentemente" --> DISK
style N8N fill:#ff6b6b,stroke:#c0392b,color:white
style PG fill:#3498db,stroke:#2980b9,color:white
style DISK fill:#2ecc71,stroke:#27ae60,color:white
end
INTERNET((Internet)) --> N8N
Puede reiniciarse sin perder datos
Base de datos externa persistente
Datos seguros en el disco físico
docker-compose.yml - Solo n8n + PostgreSQL
Este archivo despliega n8n + PostgreSQL de forma simple, sin proxies reversos ni complejidades adicionales. Solo dos servicios: n8n y la base de datos.
services:
#################################################################
# SERVICIO 1: PostgreSQL (La solución al problema de SQLite)
#################################################################
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
# 💾 CLAVE: Volumen persistente
# Los datos se guardan en el disco, NO en el contenedor
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- n8n-internal
# Verificación de salud
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
start_period: 30s
interval: 10s
timeout: 5s
retries: 5
#################################################################
# SERVICIO 2: n8n (La aplicación)
#################################################################
n8n:
image: n8nio/n8n:latest
restart: unless-stopped
# Puerto expuesto para acceder a n8n
ports:
- "5678:5678"
environment:
# Configuración para usar PostgreSQL (NO SQLite)
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
# Llave de encriptación (¡Guárdala!)
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
# Configuración general
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://${N8N_HOST}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n-internal
# Espera a que PostgreSQL esté lista
depends_on:
postgres:
condition: service_healthy
#################################################################
# INFRAESTRUCTURA
#################################################################
networks:
n8n-internal:
driver: bridge
volumes:
n8n_data:
postgres_data: # ¡Datos persistentes aquí!
Configuración de Variables (Secreto)
Nunca debe compartirse públicamente. Aquí definimos los valores reales.
# Dominio donde vivirá la app
N8N_HOST=n8n.adcon.dev
N8N_PORT=5678
# Zona horaria (Muy importante para automatizaciones que corren a cierta hora)
GENERIC_TIMEZONE=America/Mazatlan
# Credenciales de la Base de Datos (El usuario y pass que usará Postgres)
POSTGRES_USER=alba_crooks
POSTGRES_PASSWORD=jkhivqakg3m2zmzhw8v3hwzu
POSTGRES_DB=n8n
# ¡LA LLAVE MAESTRA!
# Si pierdes esto, pierdes acceso a tus credenciales de Google/Slack/etc dentro de n8n.
N8N_ENCRYPTION_KEY=IsXnOohoz1UpSirWZfPrYD7YMp+UgLYHWS8+buDKJhgXyj9Mlb20B6eCBINEc6Sn7VSoquwdwAd5cF/dM4PUSw==
¿Por qué Docker Compose y Render PostgreSQL resuelven lo mismo?
Tanto Docker Compose con PostgreSQL como Render con PostgreSQL como servicio solucionan exactamente el mismo problema: la pérdida de datos de SQLite en contenedores efímeros.
Creas dos contenedores separados:
Creas dos servicios separados:
En ambos casos, la solución es la misma:
n8n es efímero y puede reiniciarse sin consecuencias
Se conectan por red, pero viven en lugares diferentes
PostgreSQL es persistente y guarda todo de forma permanente
La magia no está en Docker o Render, está en usar PostgreSQL como servicio externo
| Aspecto | Docker Compose | Render PostgreSQL |
|---|---|---|
| Dónde viven los datos | Volumen Docker en tu servidor | Infraestructura de Render (gestionada) |
| Quién gestiona la DB | Tú (manualmente) | Render (automático) |
| Backups | Debes configurarlos tú | Automáticos (según el plan) |
| Escalabilidad | Limitada a tu servidor | Fácil escalado (cambiar plan) |
| Problema que resuelve | ✅ Pérdida de datos SQLite | ✅ Pérdida de datos SQLite |
| Principio arquitectónico | Separación App ↔ DB | Separación App ↔ DB |
No importa si usas Docker Compose en tu servidor o PostgreSQL como servicio en Render: ambos implementan el mismo patrón arquitectónico de separación entre aplicación y datos.
La clave está en que PostgreSQL (la base de datos) viva separada e independiente de n8n (la aplicación). Así, cuando n8n se reinicia o actualiza, tus datos están seguros en otro lugar.