Point-in-time recovery es un método de restauración que reaplica un log de cambios sobre un backup base para reconstruir la base de datos en cualquier segundo. El escenario para el que existe no es la falla de hardware — de eso se encarga la replicación — sino el humano: una migración que corrompió filas a las 14:32, un script que borró el tenant equivocado. El PITR responde con lo único que ayuda: la base de datos exactamente como estaba a las 14:31:59.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| Snapshot | Una fotografía — la restauración aterriza en el momento en que se tomó |
| PITR | Backup base + log de cambios reaplicado — aterriza en cualquier segundo |
| RPO | Cuántos datos recientes puedes perder — lo fija la frecuencia de captura |
| RTO | Cuánto puede tardar la restauración — lo fijan el tamaño y la mecánica |
| El reparto | Un BaaS corre la mecánica; los objetivos y los simulacros siguen siendo tuyos |
El mecanismo, en una sesión de trabajo
-- El log de cambios es la materia prima: cada escritura confirmada, en orden.
-- Antes de un trabajo riesgoso, puedes dejarle un marcador con nombre:
SELECT pg_create_restore_point('before_pricing_migration');
-- Recuperación = backup base + replay, detenido donde tú digas:
-- restaura el backup base tomado a las 02:00
-- reaplica el log hacia adelante…
-- …y detente justo antes del daño:
-- recovery_target_time = '2026-08-05 14:31:59+00'
-- (o recovery_target_name = 'before_pricing_migration')
-- Todo lo confirmado antes del objetivo existe; nada posterior existe.
Este es el write-ahead log haciendo doble turno: el mismo registro ordenado que da durabilidad a las transacciones se convierte, cuando se archiva continuamente, en una máquina del tiempo. Las bases de datos de documentos ejecutan la jugada idéntica con el oplog — captura el stream de operaciones, reaplícalo sobre un snapshot, detente a demanda (PostgreSQL lo llama archivado continuo; MongoDB documenta la misma arquitectura sobre snapshots del sistema de archivos).
Después de cualquier restauración, el paso de verificación del simulacro es a nivel de aplicación — confirma que la línea de tiempo aterrizó donde debía:
// JavaScript / Node.js — Back4app JS SDK
// Restore drill: verify the restored data lines up with the incident timeline
const incident = new Date('2026-08-05T14:32:00Z'); // when the bad deploy hit
const latest = new Parse.Query('Order');
latest.lessThan('createdAt', incident);
latest.descending('createdAt');
const lastGood = await latest.first(); // newest order before the incident
const after = new Parse.Query('Order');
after.greaterThanOrEqualTo('createdAt', incident);
const leaked = await after.count(); // must be 0 on a clean PITR restore
console.log(`last good write: ${lastGood?.get('createdAt')}`);
console.log(`rows past the recovery target: ${leaked}`); // Flutter / Dart — Back4app Flutter SDK
// Restore drill: verify the restored data lines up with the incident timeline
final incident = DateTime.parse('2026-08-05T14:32:00Z'); // the bad deploy
final latest = QueryBuilder<ParseObject>(ParseObject('Order'))
..whereLessThan('createdAt', incident)
..orderByDescending('createdAt')
..setLimit(1);
final lastGood = await latest.query(); // newest order before the incident
final after = QueryBuilder<ParseObject>(ParseObject('Order'))
..whereGreaterThanOrEqualsTo('createdAt', incident);
final leaked = await after.count(); // must be 0 on a clean PITR restore
print('last good write: '
'${(lastGood.results?.first as ParseObject?)?.createdAt}');
print('rows past the recovery target: ${leaked.count}'); // iOS / Swift — Back4app Swift SDK
// Restore drill: verify the restored data lines up with the incident timeline
let incident = ISO8601DateFormatter()
.date(from: "2026-08-05T14:32:00Z")! // when the bad deploy hit
let latest = Order.query("createdAt" < incident)
.order([.descending("createdAt")])
.limit(1)
latest.first { result in // newest order before the incident
if case .success(let lastGood) = result {
print("last good write: \(String(describing: lastGood.createdAt))")
}
}
let after = Order.query("createdAt" >= incident)
after.count { result in // must be 0 on a clean PITR restore
if case .success(let leaked) = result {
print("rows past the recovery target: \(leaked)")
}
} // Android / Kotlin — Back4app Android SDK
// Restore drill: verify the restored data lines up with the incident timeline
val incident = Date(1754404320000L) // 2026-08-05T14:32:00Z, the bad deploy
val latest = ParseQuery.getQuery<ParseObject>("Order")
latest.whereLessThan("createdAt", incident)
latest.orderByDescending("createdAt")
latest.limit = 1
latest.findInBackground { lastGood, _ -> // newest order before the incident
println("last good write: ${lastGood?.firstOrNull()?.createdAt}")
}
val after = ParseQuery.getQuery<ParseObject>("Order")
after.whereGreaterThanOrEqualTo("createdAt", incident)
after.countInBackground { leaked, e -> // must be 0 on a clean PITR restore
if (e == null) println("rows past the recovery target: $leaked")
} Cómo una restauración llega a las 14:31:59
Del mecanismo se desprenden dos propiedades. Primera, el RPO lo fija la frecuencia de captura: logs enviados cada pocos segundos significan segundos de pérdida máxima, sin importar cuándo corrió el último snapshot. Segunda, el RTO lo fija la distancia de replay: restaurar hasta las 23:00 desde una base de las 02:00 significa reaplicar 21 horas de escrituras — razón por la cual los sistemas con PITR siguen tomando snapshots frecuentes, no por granularidad sino para acortar la pista.
Snapshots vs. PITR
| Dimensión | Solo snapshots | PITR (base + replay de log) |
|---|---|---|
| Granularidad de restauración | Los momentos en que corrieron los snapshots | Cualquier segundo de la ventana |
| RPO típico | Horas (el hueco del calendario) | Segundos a minutos |
| Costo de almacenamiento | Bajo — n copias | Mayor — copias + archivo continuo de log |
| Velocidad de restauración | Rápida — copiar de vuelta | Más lenta — copiar + reaplicar |
| Ajuste al error humano | Pierdes todo desde el último snapshot | Pierdes casi nada anterior al error |
| Complejidad | Mínima | Real — archivado, orden, objetivos |
¿Qué garantía de recuperación necesitas realmente?
| Si perder… es sobrevivible | Entonces necesitas | Vigila |
|---|---|---|
| Un día de escrituras | Snapshots nocturnos | La duración de la retención |
| Una hora | Snapshots + incrementos frecuentes | Que el calendario de verdad dispare |
| Minutos o menos | Captura continua de log (PITR) | El lag del archivado — ese es tu RPO |
| Nada, nunca | PITR + replicación síncrona | Costo y latencia de escritura, con precio honesto |
Casos de uso comunes
- El deploy malo. Una migración o un hotfix corrompe datos a media tarde — restaura al segundo anterior a su salida.
- Borrados de dedo gordo. El tenant, la colección o el WHERE equivocado — recupera hasta justo antes de que corriera la sentencia, muchas veces en una base desechable para extraer solo lo perdido.
- Ransomware y cuentas comprometidas. Rebobina hasta antes de que la intrusión tocara los datos — con cifrado en reposo protegiendo las propias copias archivadas.
- Retención por cumplimiento. Los productos regulados deben probar la recuperabilidad — ventanas documentadas, restauraciones probadas, simulacros auditables.
- Ensayo previo al lanzamiento. El simulacro de restauración como requisito de release: los equipos que ya restauraron a un timestamp una vez lo hacen con calma la noche en que importa.
¿Deberías confiar en los backups por defecto? Matriz de decisión
| Los defaults bastan cuando… | Invierte más allá de ellos cuando… |
|---|---|
| Perder un día de datos es molesto, no fatal | Las escrituras son dinero — pedidos, libros contables, reservas |
| El producto es pre-lanzamiento o interno | Una hora de pérdida es una catástrofe de soporte |
| Los datos son reconstruibles desde otra fuente | La base de datos es la única fuente de la verdad |
| Nadie ha pedido garantías de recuperación | Un contrato o un regulador nombra cifras de RPO/RTO |
| Nunca has necesitado una restauración | Ya necesitaste una — y fue tensa |
Ofrezca lo que ofrezca la plataforma, tres decisiones siguen siendo tuyas: el RPO que tu producto puede sobrevivir, el RTO que tus usuarios van a tolerar y la cadencia de simulacros que mantiene honestos ambos números — la disciplina que la guía de planificación de contingencias del NIST formaliza así: define objetivos y luego prueba contra ellos.
Limitaciones y trade-offs
- La replicación no es recuperación. Las réplicas replican el error en segundos; solo los backups alcanzan el estado anterior a él. Herramientas distintas, clases de falla distintas.
- La ventana es finita. El PITR alcanza cualquier segundo — dentro de la retención. El daño descubierto después de que la ventana cierra es permanente; dimensiona la retención según el tiempo de detección, no solo según el precio del almacenamiento.
- El replay toma tiempo. Las restauraciones con mucho log pueden alargarse; tu RTO real se mide con simulacros, no lo cotizan los dashboards.
- Las restauraciones llegan enteras. El PITR clásico reconstruye la base de datos en un timestamp; extraer las filas perdidas de una sola tabla implica restaurar en una instancia desechable y copiar desde ahí — planifica ese flujo.
- Un backup no probado es un rumor. Fallas silenciosas de export, credenciales expiradas, runbooks inexistentes — cada una es invisible hasta que un simulacro o un desastre la encuentra. Los simulacros salen más baratos.
PITR y backups en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Los backups de la base de datos gestionada corren según calendario sin configuración, y restaurar es una operación de dashboard en lugar de una noche de arqueología de logs — la mitad de snapshots y mecánica de este artículo, absorbida por la plataforma. La mitad que se queda contigo es la de decidir: tus metas de RPO y RTO, tus necesidades de retención y el simulacro trimestral en el que las pestañas de código de arriba verifican que la línea de tiempo restaurada es exactamente la que pediste.
Preguntas frecuentes
¿Qué es point-in-time recovery en términos simples?
Una restauración capaz de aterrizar en cualquier momento, no solo en los horarios programados de backup. El motor parte de un backup base y reaplica su log de cambios — cada escritura confirmada, en orden — deteniéndose en el segundo que tú indiques. En lugar de perder todo desde el snapshot de anoche, pierdes solo lo que ocurrió después de las 14:31:59, el segundo anterior al incidente.
¿Cuál es la diferencia entre un snapshot y PITR?
La granularidad. Un snapshot es una fotografía: restaurar aterriza exactamente en el momento en que se tomó, y todo lo posterior se pierde. PITR es una película: backup base más captura continua de log te dejan detener la reproducción en cualquier punto de la ventana de retención. Los snapshots son más simples y baratos de mantener; PITR convierte la recuperación de "¿qué noche?" en "¿qué segundo?".
¿Qué son RPO y RTO?
Los dos números de los que toda conversación sobre backups trata en secreto. RPO — recovery point objective — es cuántos datos recientes puedes permitirte perder, definido por la frecuencia de backup o de envío de logs. RTO — recovery time objective — es cuánto puede tardar la restauración, definido por el tamaño de los datos y la mecánica del proceso. Los snapshots diarios dan un RPO de horas; la captura continua de log lo encoge hacia segundos.
¿La replicación reemplaza a los backups?
No — la replicación es disponibilidad, no recuperación. Una réplica copia fielmente todo lo que hace el primario, incluido el DROP TABLE que corriste por error; en segundos todas las copias están de acuerdo en el daño. Los backups y el PITR existen precisamente para alcanzar un estado *anterior* al error, que ninguna cantidad de replicación preserva. Necesitas ambos, para clases de falla distintas.
¿Con qué frecuencia deberían correr los backups?
Trabaja hacia atrás desde tu RPO. Si perder un día de escrituras es sobrevivible, los snapshots nocturnos bastan; si una hora duele, agrega incrementos más frecuentes; si los minutos importan, necesitas captura continua de log — y en ese punto la frecuencia de snapshots gobierna la velocidad de restauración, no la pérdida de datos. Sea cual sea el calendario, la duración de la retención decide hasta cuándo los errores siguen siendo corregibles.
¿Por qué importan los simulacros de restauración?
Porque un backup no probado es una hipótesis, no un plan. Los simulacros exponen las fallas que solo aparecen en la práctica: exports rotos en silencio, restauraciones que tardan nueve horas contra un RTO de una, credenciales faltantes, pasos sin documentar. Un simulacro trimestral — restaurar en un entorno desechable, verificar los datos, cronometrar el proceso — convierte la hipótesis en un procedimiento ensayado.
¿Qué debo verificar después de restaurar una base de datos?
Verifica primero la línea de tiempo: los registros más nuevos deben quedar justo antes del objetivo de recuperación, y nada debe existir después de él. Luego verifica la integridad — conteos de filas contra lo esperado, invariantes críticas, referencias que deben resolver. Por último verifica la aplicación: inicia sesión, corre los flujos principales, confirma que los jobs en segundo plano retoman limpios. Las restauraciones que "terminaron" aún pueden estar mal de las tres formas.
¿Quién maneja los backups en un BaaS — la plataforma o yo?
La mecánica es de la plataforma: snapshots, captura de log, almacenamiento, herramientas de restauración. Los objetivos siguen siendo tuyos: elegir RPO y RTO para tu producto, conocer la ventana de retención, correr simulacros de restauración y mantener un export independiente si la política lo exige. Un backend gestionado elimina la plomería, no la responsabilidad de decidir cómo se ve una pérdida sobrevivible.