Skip to content

Commit 0dabe13

Browse files
committed
docs: clarify SQLite production viability and backup strategies
1 parent 197a881 commit 0dabe13

4 files changed

Lines changed: 135 additions & 6 deletions

File tree

content/docs/configure/storage.cn.mdx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ new StorageServicePlugin({
4141

4242
在 standalone 模式(无项目执行 `os start`)下,运行时会在 `~/.objectstack/data/uploads/` 下自动配置本地存储。
4343

44-
**不适合生产**,除非你只有一个节点并能容忍该节点磁盘故障导致的文件丢失。多节点或需要持久化的场景请使用 S3 兼容存储。
44+
**是否适合生产取决于部署形态:**
45+
46+
- ✅ 桌面端应用、单节点内部工具、边缘 / 本地一体机 —— 本地存储完全可以,
47+
只要把 `uploads/` 目录纳入文件系统备份(桌面端应用也可以把它放在
48+
用户控制的同步目录里)。
49+
- ❌ 多节点、多可用区,或者任何需要跨区域持久化的场景 —— 请使用 S3
50+
兼容存储。
4551

4652
## S3 兼容(生产)
4753

content/docs/configure/storage.mdx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@ new StorageServicePlugin({
4747
In standalone mode (`os start` with no project), the runtime configures
4848
local storage automatically under `~/.objectstack/data/uploads/`.
4949

50-
**Not suitable for production** unless you have one node and tolerate
51-
file loss on that node's disk. Use S3-compatible storage for anything
52-
multi-node or durable.
50+
**Production fit depends on the deployment shape:**
51+
52+
- ✅ Desktop apps, single-node internal tools, edge / on-prem
53+
appliances — local storage is fine, as long as the `uploads/`
54+
directory is included in your filesystem backup (or lives on a
55+
user-controlled sync folder for desktop apps).
56+
- ❌ Multi-node, multi-AZ, or anything that needs cross-region
57+
durability — use S3-compatible storage.
5358

5459
## S3-compatible (production)
5560

content/docs/operate/backup.cn.mdx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,68 @@ ObjectOS **不**需要对其容器文件系统做单独备份。缓存目录
3131
| PostgreSQL | 持续 WAL 归档 + 基础备份;支持时间点恢复 |
3232
| Turso / libSQL | 使用平台的备份功能;本地导出为 SQLite 作冷备 |
3333
| MongoDB | 副本集快照;通过 oplog 实现 PITR |
34-
| SQLite(仅限单节点评估| 运行时空闲时做文件级快照;**不适合**生产 |
34+
| SQLite(单节点 / 桌面| 启用 WAL 模式 + 用 `VACUUM INTO` 或 Online Backup API 做热快照;如需更低 RPO 可叠加 Litestream 持续复制 —— 见下方 [SQLite 部署](#sqlite-部署) |
3535

3636
无论使用哪种驱动,都需验证:
3737

3838
- 备份能在客户的 RPO 内完成;
3939
- 一个全新数据库能基于同一份产物启动 ObjectOS 并对外服务;
4040
- 至少每季度执行一次端到端的恢复演练。
4141

42+
## SQLite 部署
43+
44+
SQLite 是默认驱动,对于**单节点**形态的 ObjectOS 完全可以用于生产
45+
—— 桌面端应用、小团队内部工具、边缘 / 本地一体机、评估环境。它的
46+
取舍是结构性的:SQLite 是单写者,因此不适合多节点 ObjectOS、高并发
47+
写入或共享数据库的部署。这些场景请使用 PostgreSQL。
48+
49+
当你确实在生产中使用 SQLite 时,让它稳定运行的配置和备份方案是配套的:
50+
51+
**运行时配置**
52+
53+
- 启用 WAL:`PRAGMA journal_mode=WAL`(读不阻塞写;崩溃安全)。
54+
- `PRAGMA synchronous=NORMAL` 是桌面 / 单机生产的常用默认值 —— 在
55+
WAL 下安全,且比 `FULL` 快得多。
56+
- 数据库文件放在**本地磁盘**上。**不要**放在 NFS、SMB,或者在运行时
57+
正在使用的情况下放在被 Dropbox / OneDrive / iCloud 同步的目录里
58+
—— SQLite 的文件锁在这些位置不可靠,这是 SQLite 部署最常见的损坏
59+
原因。
60+
61+
**热快照(无需停机)**
62+
63+
运行时继续对外服务的同时,可以用 SQLite 的 Online Backup API 或
64+
`VACUUM INTO` 生成一致性快照:
65+
66+
```sql
67+
VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite';
68+
```
69+
70+
按照你的 RPO 节奏用 cron、systemd timer 或运行时内置 scheduler 触发。
71+
给每份快照打上当时所用的产物版本标签,以便将数据库和产物作为一组
72+
回滚(见下方 [产物版本化](#产物版本化))。
73+
74+
**异地副本**
75+
76+
本地快照扛不住磁盘故障。把每份快照推送到可持续存储:
77+
78+
- 服务器 / VM:推到 S3 或任何 S3 兼容 bucket(你大概率已经为
79+
`storage` 能力配过一个了)。
80+
- 桌面端应用:把快照写入用户控制的同步目录(OneDrive / iCloud /
81+
Google Drive)—— 这里可以接受,因为快照文件是**关闭且不可变**的,
82+
和活动数据库不同。
83+
84+
**持续复制(更低 RPO)**
85+
86+
在不放弃 SQLite 的前提下要拿到分钟级以下的 RPO,把
87+
[Litestream](https://litestream.io) 与 ObjectOS 进程一起跑。它把 WAL
88+
流式复制到 S3 兼容存储,并支持时间点恢复。当单节点 SQLite 部署需要
89+
近零数据丢失时,这是推荐路径。
90+
91+
**恢复**
92+
93+
停掉运行时,用选定的快照替换数据库文件(或执行 `litestream
94+
restore`),用产生该快照时所对应的产物版本重新启动运行时。
95+
4296
## 产物版本化
4397

4498
把发布的产物视为不可变。给每份产物打上其编译所用的发布 id 标签
@@ -57,6 +111,7 @@ ObjectOS **不**需要对其容器文件系统做单独备份。缓存目录
57111
| 等级 | RPO | RTO | 备注 |
58112
|---|---|---|---|
59113
| 评估 / 演示 | 尽力而为 | 尽力而为 | SQLite 快照即可 |
114+
| 桌面端应用 / 小团队单节点 | ≤ 1 小时(快照)或 ≤ 秒级(Litestream) | 分钟级 | SQLite + WAL + 定时 `VACUUM INTO` + 异地副本 |
60115
| 单租户生产 | ≤ 15 分钟 | ≤ 1 小时 | 托管 PostgreSQL + PITR + 热镜像 |
61116
| 多租户 / 受监管 | ≤ 5 分钟 | ≤ 30 分钟 | 高可用数据库 + 多可用区 ObjectOS + 经过演练的 runbook |
62117

content/docs/operate/backup.mdx

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Match the strategy to the driver:
3131
| PostgreSQL | Continuous WAL archiving + base backup; point-in-time restore |
3232
| Turso / libSQL | Use the platform's backup feature; export to SQLite locally for cold copy |
3333
| MongoDB | Replica-set snapshots; oplog for PITR |
34-
| SQLite (single-node evaluation only) | File-level snapshot when the runtime is idle; **not** production-grade |
34+
| SQLite (single-node / desktop) | WAL mode + hot snapshots via `VACUUM INTO` or the Online Backup API; optionally Litestream for continuous replication — see [SQLite deployments](#sqlite-deployments) below |
3535

3636
Whatever the driver, validate that:
3737

@@ -40,6 +40,68 @@ Whatever the driver, validate that:
4040
traffic;
4141
- restore tests are exercised end-to-end at least once a quarter.
4242

43+
## SQLite deployments
44+
45+
SQLite is the default driver and is a legitimate production choice for
46+
**single-node** ObjectOS — desktop apps, internal tools for a small
47+
team, edge / on-prem appliances, evaluation environments. The trade-off
48+
is structural: SQLite is single-writer, so it does not fit multi-node
49+
ObjectOS, high concurrent write throughput, or shared-database
50+
deployments. For those, use PostgreSQL.
51+
52+
When you do run SQLite in production, the configuration that makes it
53+
safe and the backup recipe go together:
54+
55+
**Runtime configuration**
56+
57+
- Enable WAL: `PRAGMA journal_mode=WAL` (readers don't block the
58+
writer; crash-safe).
59+
- `PRAGMA synchronous=NORMAL` is the usual desktop/single-node default
60+
— safe with WAL, much faster than `FULL`.
61+
- Keep the database file on **local disk**. Do **not** put it on NFS,
62+
SMB, or inside a folder synced by Dropbox / OneDrive / iCloud while
63+
the runtime is running — SQLite's locking is unreliable on those and
64+
this is the most common way SQLite deployments corrupt.
65+
66+
**Hot snapshot (no downtime)**
67+
68+
The runtime keeps serving traffic while you take a snapshot using
69+
SQLite's Online Backup API or `VACUUM INTO`:
70+
71+
```sql
72+
VACUUM INTO '/var/backups/objectos/db-2026-05-27T13-00Z.sqlite';
73+
```
74+
75+
Schedule it (cron, systemd timer, or the in-process scheduler) at a
76+
cadence matching your RPO. Tag each snapshot with the artifact version
77+
that produced it so you can roll database + artifact back together
78+
(see [Artifact versioning](#artifact-versioning) below).
79+
80+
**Offsite copy**
81+
82+
A local snapshot doesn't survive disk loss. Push each snapshot to
83+
durable storage:
84+
85+
- Server / VM: push to S3 or any S3-compatible bucket (you likely
86+
already have one configured for the `storage` capability).
87+
- Desktop app: write the snapshot to a user-controlled sync folder
88+
(OneDrive / iCloud / Google Drive) — acceptable here because the
89+
snapshot file is **closed and immutable**, unlike the live database.
90+
91+
**Continuous replication (lower RPO)**
92+
93+
For sub-minute RPO without giving up SQLite, run
94+
[Litestream](https://litestream.io) alongside the ObjectOS process. It
95+
streams the WAL to S3-compatible storage and supports point-in-time
96+
restore. This is the recommended path when a single-node SQLite
97+
deployment needs near-zero data loss.
98+
99+
**Restore**
100+
101+
Stop the runtime, replace the database file with the chosen snapshot
102+
(or run `litestream restore`), start the runtime against the same
103+
artifact version that produced the snapshot.
104+
43105
## Artifact versioning
44106

45107
Treat published artifacts as immutable. Tag each artifact with the
@@ -61,6 +123,7 @@ A workable starting target for customer deployments:
61123
| Class | RPO | RTO | Notes |
62124
|---|---|---|---|
63125
| Evaluation / demo | best-effort | best-effort | SQLite snapshot is fine |
126+
| Desktop app / small-team single-node | ≤ 1 hour (snapshots) or ≤ seconds (Litestream) | minutes | SQLite + WAL + scheduled `VACUUM INTO` + offsite copy |
64127
| Single-tenant production | ≤ 15 min | ≤ 1 hour | Managed PostgreSQL with PITR + warm image |
65128
| Multi-tenant / regulated | ≤ 5 min | ≤ 30 min | HA database + multi-AZ ObjectOS + tested runbook |
66129

0 commit comments

Comments
 (0)