Course contentsShow
← Databases & SQL
Lesson 550 of 1,9535. Relational Schema ArchitectureFree lesson

Designing for Disaster Recovery

Incorporate structural elements that facilitate point-in-time recovery and data restoration.

In this lesson, you will learn how to structure your relational schema to ensure your data can be accurately restored to a specific moment in time during a catastrophic failure.

When we talk about disaster recovery (DR) at the schema level, we aren't just talking about backups; we are talking about recoverability. If your database crashes, you need to be able to roll back to a "known good state" without breaking the logical integrity of your data.

Structural Elements for Recovery

To facilitate Point-in-Time Recovery (PITR), your schema design must minimize "dangling" dependencies and ensure that every record can be traced back to its origin.

  1. Immutable Audit Trails: Instead of updating rows in place (which overwrites history), use Append-Only patterns where possible. By keeping historical states, you allow for easier restoration if a malicious UPDATE or DELETE command destroys current records.
  2. Deterministic Sequence IDs: Use BIGINT or UUID sequences that are strictly monotonically increasing. This ensures that when you replay logs to restore a database to a specific time, the transaction order remains consistent.
  3. Soft-Delete Flags: Avoid DELETE operations. Instead, implement a is_deleted or valid_to column. This prevents accidental data loss during application-level bugs and makes restoration as simple as flipping a bit.

Example: The Audit-Friendly Table

Consider an Orders table designed for resilience. Instead of just storing the current state, we keep an immutable log:

CREATE TABLE Orders (
    order_id UUID PRIMARY KEY,
    customer_id INT,
    status VARCHAR(50),
    -- Essential for PITR and consistency
    sys_version TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_active BOOLEAN DEFAULT TRUE
);

By adding a sys_version or valid_from column, you can query your data as it existed at any specific hour in the past. If a process corrupts your data, you don't need to roll back the entire database to a cold backup; you can simply reconstruct the state by filtering for the highest sys_version that predates the corruption. This structural choice makes your schema inherently "recoverable" rather than just "backup-able."

Key Takeaway: Designing for disaster recovery requires shifting from destructive operations to append-only patterns and versioned records, ensuring the database state is always queryable at any historical point in time.