Skip to content

Services & providers

A service is a named, stateful dependency of your project — a database, cache, or object store — that devflow branches alongside your code. Each service is backed by a provider that knows how to create, clone, switch, and destroy per-workspace instances.

ProviderTypeIsolationEngines
Local Dockertype: localphysical — one CoW container per workspacePostgreSQL, ClickHouse, MySQL, generic (any image)
Shared enginetype: shared (or implied)logical — one global container, one db/bucket/index per workspacePostgreSQL, ClickHouse, Redis, RustFS (S3-compatible)
Cloud (experimental)type: neon / dblab / xataprovider-managed branchingPostgreSQL
Pluginservice_type: pluginup to the pluginanything — JSON-over-stdio protocol

Multiple services coexist in one project (e.g. CoW Postgres + shared Redis + RustFS), and each declares auto_workspace — whether it follows devflow workspace creation automatically (default true) or stays global.

services:
- name: app-db
type: local
service_type: postgres
default: true # target of `-s`-less commands
local:
image: postgres:17
- name: cache
service_type: redis # shared engine, DB index per workspace
- name: storage
service_type: rustfs # shared engine, bucket per workspace
devflow switch -c feature/x
materialize Git worktree / jj workspace
for each service with auto_workspace:
local: clone parent's data dir (CoW) → start container on its own port
shared: CREATE DATABASE <service_key> TEMPLATE <parent_service_key>
(or create an isolated bucket / DB index)
lifecycle hooks fire → .env.local updated, migrations run

Workspace filtering (git.workspace_filter_regex, exclude_workspaces) and env toggles (DEVFLOW_AUTO_CREATE=false, …) control when this fires. An ordinary in-place git checkout does not provision a devflow workspace; installed hooks still adopt manually created linked worktrees. See configuration.

For type: local, creating a workspace clones the parent’s entire data directory. On a CoW filesystem the clone is near-instant and uses almost no extra disk — only blocks that change afterwards are duplicated.

FilesystemMethod
APFS (macOS)Native clonefilefile
ZFS (Linux)dataset snapshot + clone (externally provisioned pool)
Btrfs / XFS (Linux)reflink copy
Anything elsefull copy fallback

devflow doctor and devflow capabilities report which method is active. With ZFS, each project gets a dataset and each workspace a zero-copy clone of the parent snapshot:

devflow/myapp # project dataset
devflow/myapp@main # snapshot of main
devflow/myapp/feature # instant clone

Each local service workspace moves through these states:

Provisioning ──▶ Running ──▶ Stopped ──▶ (deleted)
│ │ │
└──────────▶ Failed ◀──────┘
StateMeaningCommands
Provisioningcontainer being created, data cloningservice create
Runningaccepting connectionsservice start, switch
Stoppedcontainer stopped, data preservedservice stop
Failedcrashed or failed to startservice logs, service reset

devflow service reset <ws> re-clones from the parent — the “give me a clean database” button, ideal for agent retries.

Every provider exposes uniform connection info per workspace — host, port, database, user, password, URL — surfaced by:

  • devflow connection <ws> [--format uri|env|json]
  • hook templates: {{ service['app-db'].url }}, {{ service.cache.port }}, …
  • devflow agent context --format json