Skip to content

Commit e26ef5c

Browse files
committed
Frame snapshots as SQLite backup artifacts
1 parent 6e46159 commit e26ef5c

1 file changed

Lines changed: 41 additions & 50 deletions

File tree

rfcs/0013-cloud-serializable-sqlite-state.md

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
---
2-
title: SQLite State Snapshot Command
2+
title: SQLite Snapshot Backup Artifacts
33
authors:
44
- giodl
55
created: 2026-06-18
6-
last_updated: 2026-06-22
6+
last_updated: 2026-07-06
77
status: draft
88
issue:
99
rfc_pr: https://github.com/openclaw/rfcs/pull/20
1010
---
1111

12-
# Proposal: SQLite State Snapshot Command
12+
# Proposal: SQLite Snapshot Backup Artifacts
1313

1414
## Summary
1515

16-
Define a narrow core `openclaw snapshot` command that gives file-syncing hosts a safe file to sync for OpenClaw-owned SQLite state.
16+
Define a narrow core `openclaw backup sqlite snapshot` command that gives file-syncing hosts a safe file to sync for OpenClaw-owned SQLite state.
1717

1818
Hosted OpenClaw environments such as Scout/Lobster persist OpenClaw state by syncing files when they are saved. Live SQLite files are the wrong sync boundary: `state/openclaw.sqlite` or `agents/<agentId>/agent/openclaw-agent.sqlite` can be incomplete without their WAL, and `*.sqlite-wal`, `*.sqlite-shm`, and `*.sqlite-journal` are process-local sidecars rather than durable artifacts.
1919

20-
The `snapshot` command provides the missing translation step. It asks SQLite to materialize a clean database artifact, verifies it, writes a manifest, and publishes the completed artifact set into a sync-owned location. That completed artifact write, not arbitrary live database churn, is what the host should sync.
20+
The SQLite snapshot backup command provides the missing translation step. It asks SQLite to materialize a clean database artifact, verifies it, writes a manifest, and publishes the completed artifact set into a sync-owned location. That completed artifact write, not arbitrary live database churn, is what the host should sync.
2121

2222
SQLite remains the hot local runtime database. This RFC does not choose a replacement database, make cloud storage mandatory, or require managed failover. It defines a state-artifact boundary: OpenClaw core owns the SQLite-aware artifact operation, while the host owns upload, retention, routing, encryption, and restore timing.
2323

@@ -43,17 +43,17 @@ Deltas do not remove this requirement. Ryan's underlying concern is that whole-f
4343
## Goals
4444

4545
- Keep SQLite as the hot local runtime database for this proposal.
46-
- Make snapshot behavior explicit through a narrow core `openclaw snapshot` command.
46+
- Make snapshot behavior explicit through a narrow core `openclaw backup sqlite snapshot` command.
4747
- Produce a host-syncable SQLite artifact and manifest from live OpenClaw SQLite state.
4848
- Handle WAL state correctly without syncing live SQLite sidecars as durable artifacts.
4949
- Make restore and verification first-class behaviors, not incidental backup side effects.
5050
- Define a reusable SQLite snapshot provider contract for OpenClaw-owned SQLite databases.
5151
- Define the state-artifact boundary that lets hosted platforms persist OpenClaw state without understanding OpenClaw's internal SQLite file layout.
5252
- Keep the command narrow: create, verify, and restore syncable SQLite artifacts.
5353
- Document host sync guidance: ignore live SQLite sidecars and sync completed snapshot artifacts/manifests instead.
54-
- Add commands under `openclaw snapshot`.
54+
- Add commands under `openclaw backup sqlite snapshot`.
5555
- Leave `openclaw backup` integration as a possible later follow-up, not part of the initial proof stack.
56-
- Keep default local OpenClaw runtime behavior unchanged unless the snapshot command is invoked.
56+
- Keep default local OpenClaw runtime behavior unchanged unless the SQLite snapshot backup command is invoked.
5757
- Avoid hot writes over network filesystems as a durability or concurrency strategy.
5858
- Treat WAL bundles as the first high-frequency optimization after full snapshot artifacts are correct.
5959
- Define lifecycle metadata needed to validate, order, restore, and audit snapshots.
@@ -81,38 +81,29 @@ Deltas do not remove this requirement. Ryan's underlying concern is that whole-f
8181

8282
### Command shape
8383

84-
Add a core `openclaw snapshot` command that owns SQLite-safe snapshot and restore workflows for OpenClaw state.
84+
Add a core `openclaw backup sqlite snapshot` command that owns SQLite-safe snapshot and restore workflows for OpenClaw state.
8585

86-
The command surface should stay direct:
86+
The command surface should stay narrow inside the existing backup area:
8787

8888
```text
89-
openclaw snapshot create
90-
openclaw snapshot verify
91-
openclaw snapshot restore
92-
openclaw snapshot list
93-
openclaw snapshot status
89+
openclaw backup sqlite snapshot create
90+
openclaw backup sqlite snapshot verify
91+
openclaw backup sqlite snapshot restore
92+
openclaw backup sqlite snapshot list
9493
```
9594

9695
The first named target shape can be:
9796

9897
```text
99-
openclaw snapshot create --target global
100-
openclaw snapshot create --agent main
101-
openclaw snapshot verify <snapshot>
102-
openclaw snapshot restore <snapshot> --target <state-dir>
98+
openclaw backup sqlite snapshot create --target global
99+
openclaw backup sqlite snapshot create --agent main
100+
openclaw backup sqlite snapshot verify <snapshot>
101+
openclaw backup sqlite snapshot restore <snapshot> --target <state-dir>
103102
```
104103

105104
This does not imply automatic scheduling, cloud storage, failover, or a new database abstraction. The core command produces and verifies the syncable artifact; the host decides where that artifact is stored and when it is restored.
106105

107-
Later, if maintainers want one user-facing home for backup and restore workflows, the same provider contract can be wired under the existing backup command surface:
108-
109-
```text
110-
openclaw backup snapshot
111-
openclaw backup restore
112-
openclaw backup status
113-
```
114-
115-
That integration is intentionally not part of the initial implementation roadmap. The first proof should stay scoped to the `snapshot` command so it can demonstrate correctness without changing the existing backup command behavior.
106+
This keeps the feature out of the top-level command namespace while still making the SQLite implication explicit. `openclaw backup create` and `openclaw backup verify` keep their existing archive behavior; `backup sqlite snapshot` is the per-database SQLite artifact path.
116107

117108
### Responsibility split
118109

@@ -129,9 +120,9 @@ OpenClaw should provide:
129120
- lifecycle metadata shape
130121
- safety rules such as no hot writes over network filesystems
131122

132-
The `snapshot` command should own the operator workflow around the core primitive:
123+
The `backup sqlite snapshot` command should own the operator workflow around the core primitive:
133124

134-
- snapshot command UX
125+
- SQLite snapshot backup command UX
135126
- local snapshot artifact creation and publication into a sync-owned artifact directory
136127
- snapshot manifest creation and verification
137128
- restore workflow orchestration
@@ -195,8 +186,8 @@ flowchart LR
195186
Metadata[lifecycle metadata]
196187
end
197188
198-
subgraph Command[Core snapshot command]
199-
Cmd[openclaw snapshot]
189+
subgraph Command[Core SQLite snapshot backup command]
190+
Cmd[openclaw backup sqlite snapshot]
200191
Manifest[snapshot manifest]
201192
LocalRepo[(local snapshot repo)]
202193
end
@@ -225,7 +216,7 @@ flowchart LR
225216
Failover -. later .-> Restore
226217
```
227218

228-
The diagram is a responsibility split, not a default managed-hosting requirement. Default local OpenClaw can run with only the runtime box. Operators and hosts use the snapshot command when they need verified snapshot and restore workflows.
219+
The diagram is a responsibility split, not a default managed-hosting requirement. Default local OpenClaw can run with only the runtime box. Operators and hosts use the SQLite snapshot backup command when they need verified snapshot and restore workflows.
229220

230221
For hosted OpenClaw, the same split becomes the host integration contract. The host can ask OpenClaw to materialize a clean artifact before upload and can hydrate local disk from a verified artifact before OpenClaw opens SQLite. The host does not need to treat live SQLite sidecars as durable sync inputs.
231222

@@ -247,7 +238,7 @@ family. Today, memory-search state is owned by the per-agent database-first
247238
store, so Phase 1 can protect it through the per-agent database target:
248239

249240
```text
250-
openclaw snapshot create --agent main
241+
openclaw backup sqlite snapshot create --agent main
251242
```
252243

253244
A future memory-search-only target would need a separate design because it
@@ -327,7 +318,7 @@ Restore artifacts should be consumed before OpenClaw opens the target database f
327318

328319
### Restore verification
329320

330-
Restore is a required behavior for `openclaw snapshot`, not an incidental backup side effect.
321+
Restore is a required behavior for `openclaw backup sqlite snapshot`, not an incidental backup side effect.
331322

332323
A restore operation must:
333324

@@ -388,13 +379,13 @@ At minimum, snapshot metadata should include:
388379
- restore source and restore point when hydrated
389380
- current writer owner or lease holder, when leases are enabled
390381

391-
The exact storage location for this metadata is implementation-defined, but `openclaw snapshot` must be able to read enough metadata to verify and restore a snapshot without opening a possibly unsafe runtime database first.
382+
The exact storage location for this metadata is implementation-defined, but `openclaw backup sqlite snapshot` must be able to read enough metadata to verify and restore a snapshot without opening a possibly unsafe runtime database first.
392383

393384
### Provider shape
394385

395386
The implementation can start as a SQLite-specific snapshot provider rather than a database abstraction layer.
396387

397-
The provider contract should be reusable by any OpenClaw feature that needs to capture or restore an OpenClaw-owned SQLite database. `openclaw snapshot` is the first proposed CLI surface, but the contract should not depend on command-only state.
388+
The provider contract should be reusable by any OpenClaw feature that needs to capture or restore an OpenClaw-owned SQLite database. `openclaw backup sqlite snapshot` is the first proposed CLI surface, but the contract should not depend on command-only state.
398389

399390
A minimal shape is:
400391

@@ -420,13 +411,13 @@ type RemoteSnapshotProvider = SqliteSnapshotProvider & {
420411

421412
This keeps SQLite runtime access local while making state artifacts portable. A local snapshot provider can be the reference implementation. Cloud/object-store providers can come later without changing the default local runtime.
422413

423-
If the design proves broadly useful, the same contract can support backup restore, startup hydration, or state migration workflows without changing the narrow `openclaw snapshot` command.
414+
If the design proves broadly useful, the same contract can support backup restore, startup hydration, or state migration workflows without changing the narrow `openclaw backup sqlite snapshot` command.
424415

425416
### Implementation roadmap
426417

427418
The implementation should be split into two phases.
428419

429-
Phase 1 is the committed snapshot command work. It proves full verified
420+
Phase 1 is the committed SQLite snapshot backup command work. It proves full verified
430421
snapshots, named OpenClaw database targets, and fresh-state restore. It should
431422
also collect the metrics that decide whether Phase 2 is worth doing:
432423

@@ -447,7 +438,7 @@ The current Phase 1 implementation stack is:
447438

448439
| PR | Purpose |
449440
| -------------------------------------------------------------------------- | --------------------------------------------- |
450-
| [openclaw/openclaw#94805](https://github.com/openclaw/openclaw/pull/94805) | Core snapshot command and safe-sync artifact |
441+
| [openclaw/openclaw#94805](https://github.com/openclaw/openclaw/pull/94805) | Core SQLite snapshot backup command and safe-sync artifact |
451442
| [openclaw/openclaw#94967](https://github.com/openclaw/openclaw/pull/94967) | Snapshot stress harness for Phase 1 greenlight |
452443

453444
Before maintainers accept this RFC or land the core command, the same
@@ -461,7 +452,7 @@ checkpoint for it. The pilot should answer:
461452
temporary files, and sidecars
462453
- how often Scout needs snapshots to meet its recovery expectations
463454
- observed snapshot artifact size and creation time for real hosted use
464-
- whether users or operators need a core `openclaw snapshot` command, a
455+
- whether users or operators need a core `openclaw backup sqlite snapshot` command, a
465456
host-owned plugin command, or both
466457
- whether Phase 2 WAL bundles are justified by measured size, timing, or
467458
frequency data
@@ -470,10 +461,10 @@ Earlier provider, CLI, and named-target slices were collapsed into
470461
[openclaw/openclaw#94805](https://github.com/openclaw/openclaw/pull/94805) so
471462
the core feature can be reviewed as one product boundary.
472463

473-
#### Phase 1 / PR A: core snapshot command and safe-sync artifact
464+
#### Phase 1 / PR A: core SQLite snapshot backup command and safe-sync artifact
474465

475466
Add the shared SQLite snapshot provider, local artifact repository, public
476-
`openclaw snapshot` command surface, named database targets, and safe-sync
467+
`openclaw backup sqlite snapshot` command surface, named database targets, and safe-sync
477468
artifact proof.
478469

479470
- `SqliteSnapshotProvider` contract
@@ -485,16 +476,16 @@ artifact proof.
485476
- user-facing core commands:
486477

487478
```text
488-
openclaw snapshot create
489-
openclaw snapshot verify
490-
openclaw snapshot restore
479+
openclaw backup sqlite snapshot create
480+
openclaw backup sqlite snapshot verify
481+
openclaw backup sqlite snapshot restore
491482
```
492483
- `--target global` for `state/openclaw.sqlite`
493484
- `--agent <agentId>` for `agents/<agentId>/agent/openclaw-agent.sqlite`
494485
- manifest fields for database role, agent id, schema version, and source path
495486
- host-sync guidance that says live SQLite sidecars are ignored and completed
496487
artifacts are the sync input
497-
- target-directory safety checks, restore manifest validation, SQLite integrity checks after restore, and docs for the `openclaw snapshot` command surface
488+
- target-directory safety checks, restore manifest validation, SQLite integrity checks after restore, and docs for the `openclaw backup sqlite snapshot` command surface
498489
- proof that OpenClaw can create a snapshot from a named database target, copy only the completed snapshot directory, restore from that copied artifact into a fresh local SQLite path, and verify the restored database
499490

500491
This proof should also document the host contract: which OpenClaw command or API materializes the artifact, which files are safe to sync, which live SQLite sidecars should be ignored, which manifest fields the host can store without interpreting SQLite internals, and what must be restored before OpenClaw opens the database.
@@ -556,7 +547,7 @@ full snapshot generation. Conservative pruning policy can remain later work.
556547

557548
After the initial PRs, follow-up RFCs or implementation PRs can consider:
558549

559-
- `openclaw backup` integration
550+
- broader `openclaw backup` archive integration using the same provider contract
560551
- object/blob storage providers
561552
- retention and scheduling
562553
- WAL bundle retention and pruning policy
@@ -569,9 +560,9 @@ This approach targets the reliability problem directly. It does not require Open
569560

570561
The database-first work in openclaw/openclaw#94646 improves this RFC because it gives snapshot a concrete target model. Snapshot does not have to invent logical database units. It can operate over the already-established global control-plane database and per-agent data-plane databases, then extend to dedicated owner stores only when those stores have comparable ownership and lifecycle metadata.
571562

572-
Calling the command `snapshot` keeps the first deliverable concrete. It describes the artifact OpenClaw needs before higher-level reliability features can exist. It also avoids overpromising automatic failover before leases, promotion, and orchestration are designed.
563+
Calling the subcommand `snapshot` under `backup sqlite` keeps the first deliverable concrete without giving it top-level command real estate. The path says what it is: a backup-area SQLite artifact, not a broad backup archive and not automatic failover.
573564

574-
Keeping the first implementation stack under `openclaw snapshot` keeps the proof small and command-scoped. Existing `openclaw backup create` and `openclaw backup verify` behavior can remain unchanged while the snapshot provider proves the harder SQLite correctness and restore semantics.
565+
Keeping the first implementation stack under `openclaw backup sqlite snapshot` keeps the proof small and command-scoped. Existing `openclaw backup create` and `openclaw backup verify` behavior can remain unchanged while the snapshot provider proves the harder SQLite correctness and restore semantics.
575566

576567
Treating remote storage as artifact storage avoids the common failure mode where object storage or network filesystems are used as if they were local disk. SQLite remains local and authoritative while running. Reliability comes from verified snapshots, manifests, restore procedures, and later WAL bundles.
577568

0 commit comments

Comments
 (0)