Policy
The policy is the foundation of this tool: one YAML file that declares what to back up, on what schedule, and how long to keep it. Everything else (env vars, the runner, the schedules) just serves the policy. It is the one file you must author.
- Loaded from the path in the
NEO4J_BACKUP_POLICYenv var (defaultpolicies/demo.yaml). - Schema (authoritative):
orchestrator/neo4j_backup_dagster/policy.py. - Validated on load: aliases must be legal Neo4j aliases, and every group's
tiermust exist undertiers.
A complete policy
Copy this, delete what you don't need, and edit it. Every field is shown. Comments mark [used] (the pipeline acts on it) vs [decl] (declarative — accepted and validated, but not wired to behavior yet).
# Two top-level keys: db_groups (a list) and tiers (a map).
db_groups:
# ----- one entry per backup group (the policy + PITR-alignment unit) -----
- id: acme # [used] group id; part of storage path + partition key
aliases: # [used] app-facing Neo4j aliases to back up (one unit each)
- acme-orders
- acme-graph
- acme-audit
tier: gold # [used] must match a key under `tiers:` below
retention_days: 30 # [used] prune deletes artifacts older than this (keeps chain head)
owner: acme-corp # [decl] reporting / ownership tag only
s3_prefix: s3://backups/acme/ # [decl] not read yet; bucket comes from BACKUP_BUCKET env
rpo_minutes: 60 # [decl] target, not enforced
rto_minutes: 120 # [decl] target, not enforced
encryption: # [decl] recorded intent; SSE-KMS is applied by your bucket
mode: sse-kms # one of: sse-kms | client-side | none
kms_key_ref: acme-key # KMS key id/alias for this group
topology: # [used] cluster shape a restore seeds into (omit on standalone)
primaries: 3 # CREATE DATABASE … TOPOLOGY 3 PRIMARIES 0 SECONDARIES
secondaries: 0
overrides: {} # [decl] per-alias cadence overrides; not wired
# (may carry `topology:` per alias — that IS wired)
# ----- a second group on a lighter tier (minimal: only the [used] fields + s3_prefix) -----
- id: globex
aliases: [globex-main]
tier: bronze
retention_days: 7
s3_prefix: s3://backups/globex/
# ----- named schedules referenced by db_group.tier -----
tiers:
gold: # [used]
full_cron: "0 2 * * *" # daily full at 02:00
diff_cron: "0 * * * *" # hourly differential
bronze:
full_cron: "0 4 * * 0" # weekly full (Sundays 04:00)
diff_cron: "0 0 * * *" # daily differential
The smallest valid group needs only id, aliases, tier, retention_days, and
s3_prefix (the last is required by the schema even though it's declarative today).
Field reference
db_groups[]
| Field | Type | Required / default | Status | Meaning |
|---|---|---|---|---|
id |
string | required | used | group identifier; part of the storage path + partition key |
restore_mode |
alias-swap | by-name |
alias-swap |
used | alias-swap (apps use aliases; restore seeds a new physical + swaps the alias — non-destructive) or by-name (#48: no alias; restore targets the database by its own name) |
aliases |
list of string | required (alias-swap) | used | app-facing Neo4j aliases to back up (one unit each). Use in alias-swap mode. |
databases |
list of string | required (by-name) | used | database names to back up/restore directly (must be legal DB names). Use in by-name mode instead of aliases. |
tier |
string | required | used | which tiers entry sets the schedule (must exist) |
retention_days |
int | 7 |
used | prune deletes artifacts older than this |
s3_prefix |
string | required | decl | not read; the bucket comes from BACKUP_BUCKET |
owner |
string | null |
decl | reporting / ownership tag |
rpo_minutes |
int | 60 |
decl | target, not enforced |
rto_minutes |
int | 120 |
decl | target, not enforced |
encryption |
object | {mode: sse-kms} |
decl | recorded intent; SSE-KMS applied by your bucket |
topology |
object | null |
used | cluster shape seeded on restore/import; omit for standalone |
overrides |
map | {} |
decl | per-alias cadence overrides; not wired (but overrides[alias].topology is — it overrides the group topology for that alias) |
db_groups[].encryption
| Field | Type | Required / default | Status | Meaning |
|---|---|---|---|---|
mode |
sse-kms | client-side | none |
sse-kms |
decl | intended at-rest encryption mode |
kms_key_ref |
string | null |
decl | KMS key id/alias for the group |
db_groups[].topology — omit entirely for standalone/single-instance (the TOPOLOGY
clause is illegal there); set it on a cluster so a restore keeps the intended redundancy
instead of the DBMS default (see RECOVERY.md, DESIGN.md §3).
| Field | Type | Required / default | Status | Meaning |
|---|---|---|---|---|
primaries |
int (≥1) | 1 |
used | primary count in the seeded TOPOLOGY clause |
secondaries |
int (≥0) | 0 |
used | secondary count in the seeded TOPOLOGY clause |
tiers{} (named schedules referenced by db_group.tier)
| Field | Type | Required / default | Status | Meaning |
|---|---|---|---|---|
full_cron |
cron string | required | used | when full backups run (the full lane) |
diff_cron |
cron string | required | used | when differential backups run (the diff lane) |
What you actually tune
The used fields: id, aliases, tier, retention_days, topology (on clusters),
and the tiers crons.
The decl fields are accepted and validated but don't change behavior yet — leave them
at sane values. (s3_prefix would become live if per-group buckets are wired.)