Backup and Restore¶
Applies to: All subscriptions
Purpose¶
Define what must be backed up, how it is verified, and how a restore is performed — including the one item whose loss no database backup can recover from.
Audience¶
Database administrators and infrastructure teams.
Prerequisites¶
- Agreed recovery point and recovery time objectives
- Backup storage, separate from the production hosts
- A scratch environment for restore rehearsals
Steps¶
1. Know what must be backed up¶
| Item | Why | Recoverable without it? |
|---|---|---|
| Database | Everything: documents, compliance evidence, masters, configuration, audit | No |
| Field encryption key | Decrypts sensitive stored values | No — and a database backup does not contain it |
| Environment configuration | Credentials and settings | Re-creatable, painfully |
| Uploaded files | Source files and generated documents | Depends on retention policy |
| TLS certificates and keys | Transport | Re-issuable |
| Supervisor configuration | Process definitions | Re-creatable |
The encryption key is the row that matters most. A database backup contains only ciphertext. Restore the database without the key and you recover rows nobody can read. Back the key up somewhere the database backup is not, and test that you can retrieve it independently.
2. Set the schedule¶
| Backup | Frequency | Retention |
|---|---|---|
| Full database | Daily | 35 days online |
| Transaction log | Hourly, or more often if the recovery point objective demands | 35 days |
| Configuration | On change | Indefinite, versioned |
| Encryption key | On change | Indefinite, in a secret store |
| Files | Daily | Per retention policy |
| Archive | Annually | Per statutory retention |
Verify: The schedule above is a recommendation, not a Complifly commitment. Replace it with the customer's agreed objectives. Recorded as assumption C1 in the Assumptions Register.
3. Protect the backups¶
| Requirement | Reason |
|---|---|
| Stored off the production host | A backup on the same host is not a backup |
| Encrypted at rest | They contain everything |
| Access restricted | Same |
| Immutable or write-once where possible | Protects against deletion, accidental or otherwise |
| Monitored | A silent failure is discovered at the worst moment |
4. Verify every backup¶
A backup that has not been verified is an assumption.
| Level | Frequency | Proves |
|---|---|---|
| Backup job succeeded | Every backup | It ran |
| Backup verified | Every backup | It is readable |
| Restore rehearsal | Monthly, minimum quarterly | It actually works |
Only the third proves recovery. The first two are necessary and insufficient.
5. Restore¶
1. Decide the target point in time
2. Provision or clear the target environment
3. Restore the database to that point
4. Restore the environment configuration
5. RESTORE THE ENCRYPTION KEY <-- most commonly forgotten
6. Restore files, if in scope
7. Start the application; read the startup log to the end
8. Verify (see below)
Step 5 is the step people miss, and its absence is not obvious: the application starts, screens load, and only the encrypted fields are unreadable.
6. Verify a restore properly¶
| Check | Pass condition |
|---|---|
| Application starts | No missing-object message in the startup log |
| Data present | Recent documents visible |
| Correctly scoped | A user of one registration sees their data — and only theirs |
| Encrypted values readable | Sensitive fields decrypt |
| Compliance evidence intact | Reference numbers, signed QR codes, acknowledgements all present |
| Documents print | A printed document scans |
| Configuration correct | Provider, mail and feature settings as expected |
| Point in time correct | The most recent transaction matches the intended point |
The scope check is the one most often skipped. Data present but invisible to users is a scope-identifier mismatch between environments — reconcile the identifiers. Never disable the isolation policies to "make the data appear"; that turns a recovery problem into a data-exposure one.
7. Restoring into a non-production environment¶
Two rules, both non-negotiable:
| Rule | Why |
|---|---|
| Replace production provider credentials with sandbox credentials immediately | A test document sent with production credentials reaches the government and permanently consumes a real document number |
| Consider whether the data should be masked | A restored copy contains real business and personal data |
Do the first before starting the application, not after.
Validation¶
| Check | Method | Pass condition |
|---|---|---|
| Backups run | Inspect history | Recent and successful |
| Backups verify | Inspect verification results | All verified |
| Restore works | Rehearse into a scratch environment | Completes within the recovery objective |
| Restored data is scoped | Sign in as a user | Sees their own data only |
| Encrypted values readable | Inspect a sensitive field | Decrypts |
| The key is independently recoverable | Retrieve it without the database backup | Succeeds |
| Objectives are met | Time the rehearsal | Within the agreed recovery time |
| Backups are off-host | Inspect storage | Separate |
| Non-production credentials swapped | Attempt a provider call from a restored copy | Reaches only the sandbox |
Troubleshooting¶
| Symptom | Cause | Action |
|---|---|---|
| Encrypted values unreadable after restore | The key was not restored | Restore the original key. Nothing else recovers them |
| Data present but users see nothing | Scope identifiers differ between environments | Reconcile the identifiers. Never disable isolation policies |
| Application refuses to start after restore | Schema older or newer than the code | Match the application version to the restored schema, then migrate forward |
| Restore takes longer than the objective | Objective set without testing | Improve the process, or revise the objective honestly |
| Backup failures noticed late | Not monitored | Alert on backup failure |
| A test document reached the government from a restored copy | Production credentials not replaced | Treat as an incident. Replace credentials before starting the application |
| Point-in-time recovery unavailable | Simple recovery model, or no log backups | Full recovery model with regular log backups |
| Log file grew without bound | Full recovery with no log backups | Configure log backups; do not switch recovery model to work around it |
| Backups exist but nobody has restored one | No rehearsal | Rehearse now. An untested backup is not a recovery capability |
Related Articles¶
- Database Requirements
- Multi-Tenancy and Row-Level Security — why scope matters after a restore
- Monthly Checks — where the rehearsal sits
- Security Hardening — the encryption key