Every app includes:

path use
/shared.db replicated SQLite
/shared/ replicated files

Open them as local paths. Writes commit locally, converge across instances and regions, and land durably in object storage. There is no database service or primary endpoint to provision.

Use these before adding a volume. A persistent volume is for software that requires a private local filesystem.

sqlite3 /shared.db <<'SQL'
CREATE TABLE IF NOT EXISTS notes(id TEXT PRIMARY KEY, body TEXT);
INSERT INTO notes VALUES('one', 'hello')
  ON CONFLICT(id) DO UPDATE SET body=excluded.body;
SELECT body FROM notes WHERE id='one';
SQL
printf 'generated once\n' > /shared/artifact.txt
cat /shared/artifact.txt

multi-writer rules

SQLite compatibility

/shared.db works transparently with programs that dynamically link the system libsqlite3: Python's stdlib, Ruby's system SQLite gem, the CLI, Rails, Django, and Go built with -tags=libsqlite3.

Bindings that statically embed SQLite cannot be intercepted. Examples include better-sqlite3, Node's built-in node:sqlite, modernc.org/sqlite, and mattn/go-sqlite3 without the system-library build tag. Rebuild against libsqlite3.so, or load the engine explicitly after opening:

SELECT load_extension('/usr/local/lib/syzy-engine.so', 'sqlite3_syzy_init');

shared files

/shared/ is a content-oriented POSIX mount for uploads, generated assets, and small blobs. Advisory locks, mmap, and O_DIRECT are not supported; put coordination in /shared.db.

mount shared files elsewhere

A shared Compose volume mounts the app's /shared/ tree at another path:

services:
  web:
    volumes: [uploads:/srv/uploads]
  worker:
    volumes: [uploads:/work/uploads]

volumes:
  uploads:
    x-kedge: {shared: true}

Both mount points refer to the same replicated file tree. One service may currently mount one shared volume path.

named databases

An app's default database follows that app. A named database can outlive and serve several apps:

kedge db create mydata
kedge db attach mydata myapp
kedge db attach mydata myworker

New instances attach immediately; existing instances pick it up when they recycle. kedge db detach myapp returns that app to its private default. The app page provides a SQL console for either kind.

previews and forks

Previews get isolated shared data. Forking branches the source database and files at one instant without copying all pages; unchanged content remains shared underneath, while later writes stay on their own branch.

kedge fork myapp myapp-experiment