Guía9 min

Backup y restore del estado de un agente IA: volúmenes, SQLite y S3

Resumen

Cómo no perder la memoria del agente al redeployar: backups nativos de Railway (schedules, límite 50% del volumen), copia consistente de SQLite con .backup o WAL, snapshots de volúmenes Docker y Fly, restore sin pisar producción, y copia offsite a S3/R2 porque borrar el volumen borra los backups nativos.

RailwayDocker
Disco con copias de seguridad etiquetadas preview y producción junto a un agente

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

Rollback devuelve el código anterior. No devuelve el sqlite que tu agente corrompió a las 2 AM. Si el estado vive en un volumen — memoria de sesión, RAG local, cola de jobs — necesitas backup y restore del dato, no solo del binario. Railway lo dice sin rodeos: borrar un volumen elimina todos sus backups nativos. Las fuentes oficiales fueron consultadas el 3 de septiembre de 2026.

Esta guía cubre el estado que duele perder: sqlite, archivos en /data, embeddings cacheados. No sustituye el backup del proveedor de Postgres gestionado — pero muchos agentes MVP empiezan con un archivo en disco.

La regla de dos capas

  1. Nativo de plataforma: snapshots Railway (daily/weekly/monthly), utilidades de volumen Fly/Docker.
  2. Offsite: pg_dump, .backup de SQLite, o railway volume files upload hacia S3/R2/Bucket — fuera del volumen que un CLI puede borrar.

Si solo tienes capa 1 y alguien ejecuta railway volume delete, pierdes código y historial. El self-hosting con Docker ya menciona cron de tarball; aquí va el procedimiento completo.

Qué respaldar en un agente

DatoTípico en¿Crítico?
sqlite / LevelDB de sesión/data, volumen RailwaySí — es la “memoria”
Índice vectorial localmismo volumenSí — tarda en reindexar
Cola de jobs (BullMQ en Redis)Redis gestionado o volumenDepende — jobs en vuelo
Logsstdout / plataformaNo para restore — ver logs
Secretosenv varsNo en el backup de disco — secretos

No copies .env al bucket sin cifrar. El backup es del estado de negocio, no de las llaves.

Railway: backups de volumen

Con un volumen montado en el servicio del agente:

  • Manual: pestaña Backups → Create backup.
  • Programado: Daily / Weekly / Monthly.
  • Restore: elige timestamp → Restore (mismo proyecto y environment).
  • Costo: incremental copy-on-write, facturado como volumen.
  • Límite: backup manual ≤ 50 % de la capacidad del volumen — si tu sqlite creció, agranda el volumen antes.

Railway CLI para archivos sueltos:

railway volume files list /
railway volume files download /data/agent.db ./agent-$(date +%F).db

Importante: el volumen se monta al arrancar el contenedor, no en build. Escribe en la ruta montada (/data), no en /app/data del layer efímero si no coincide con el mount.

Offsite recomendado: template postgres-s3-backups adaptado a sqlite, o cron dentro del contenedor que sube a R2. Los backups nativos son capa cómoda, no capa única.

SQLite: copia consistente

Copiar agent.db con cp mientras hay escrituras puede dejarte un archivo corrupto. SQLite documenta la API Online Backup y el comando CLI .backup:

sqlite3 /data/agent.db ".backup '/backup/agent-$(date +%F).db'"

Con WAL activado, un file copy puede ser seguro si el proceso hace checkpoint — pero .backup es el camino documentado. Para producción seria, Litestream replica WAL a S3 en tiempo real (mención como patrón, no como fuente primaria del post).

Ensayo: restaura el .backup en Preview y confirma que el agente recuerda una sesión de prueba.

Docker en VPS

Del tutorial Docker:

docker run --rm \
  -v agente_data:/data \
  -v $PWD/backups:/backup \
  alpine sh -c 'sqlite3 /data/agent.db ".backup /backup/agent-$(date +%F).db"'

O tarball del volumen nombrado:

docker run --rm -v agente_data:/data -v $PWD:/backup alpine \
  tar czf /backup/agente-data-$(date +%F).tgz -C /data .

Programa en cron del host (no dentro del contenedor que puede morir). Retención: 7 diarios + 4 semanales; copia una semanal offsite.

Restore: para el compose, restaura el archivo, docker compose up -d, verifica healthcheck.

Fly.io: volúmenes regionales

Fly monta volúmenes en una región — no migran solos entre regiones. Backup vía:

  • Snapshot de la plataforma (según plan y tooling Fly).
  • fly ssh console + .backup sqlite a un almacenamiento externo.
  • Replicar estado en DB gestionada si necesitas multi-región.

Restore en Fly suele ser: nuevo volumen + copiar datos + remount — planifícalo antes del incidente. Un rollback de código no monta el volumen viejo automáticamente.

Flujo de restore sin incidente mayor

Capas de backup nativo y offsite para el estado de un agente

  1. Detecta corrupción o borrado (usuario, bug, deploy).
  2. Para escrituras — modo mantenimiento o apaga webhook (Telegram sin webhook = agente mudo).
  3. Elige backup — el anterior al deploy sospechoso, no el más reciente si el bug ya escribió basura.
  4. Restore en staging primero si tienes environment separado.
  5. Remonta volumen o swap archivo sqlite.
  6. Health 200 → reabre webhook → monitor alertas.

Railway restore nativo reemplaza el contenido del volumen en el mismo environment — hazlo con el servicio detenido o en ventana de mantenimiento.

Errores comunes

Errores típicos al respaldar estado de agentes en producción

ErrorConsecuenciaFix
Estado en filesystem efímero del contenedorSe pierde en cada deployVolumen en /data
Solo backup nativo Railwayvolume delete = adiósOffsite semanal
Restore el backup más nuevoReintroduces el bug que corrompió datosBackup anterior al incidente
cp sqlite con tráficoArchivo corrupto.backup o Litestream
Backup incluye PII sin cifrarIncidente de privacidadCifrar bucket; minimizar datos

Relación con rollback

AcciónQué revierte
Rollback de deployCódigo e imagen
Restore de volumenArchivos en disco
Rotación de secretosLlaves comprometidas

Los tres son ortogonales. Un deploy malo + sqlite sano → rollback. Un bug que escribió mal la DB → restore de backup, no rollback.

Checklist

  • Estado del agente en volumen persistente (no layer efímero)
  • Backup nativo programado (Railway daily o cron Docker)
  • Copia offsite ≥ semanal (S3/R2/Bucket)
  • Restore ensayado en staging este mes
  • Runbook: quién aprueba restore y cómo apagar webhook
  • Retención definida (cuántos días de conversaciones guardas)

Un agente sin backup de estado es un chatbot con amnesia selectiva: funciona hasta el día que no.


Siguiente paso: cablea alertas para saber que el servicio murió y logs para saber por qué. Si el estado aún no existe porque no desplegaste, el curso gratuito deja un sqlite local para practicar .backup antes de subirlo.