Skip to main content

ENABLE MANAGED CONFIG FOR MULTI-INSTANCE SERVE

This guide shows you how to enable managed config so that multiple swamp serve instances share configuration through the datastore. Config changes on one instance — creating a model, pulling an extension, updating a vault — propagate to every other instance automatically.

Prerequisites

  • A shared datastore accessible by all instances (e.g., S3 or GCS)
  • The datastore extension must support the configRefresh sync capability:
    • @swamp/s3-datastore >= 2026.08.27
    • @swamp/gcs-datastore >= 2026.08.27
  • A running multi-instance deployment — see Run a Multi-Instance Deployment

Check your extension version:

$ swamp extension list --json | grep s3-datastore

If the version predates 2026.08.27, update the extension:

$ swamp extension pull @swamp/s3-datastore

1. Seed pulled-extension sources into the datastore

Before migrating config, ensure that pulled-extension source files are present in the remote datastore. config migrate copies from the local .swamp/pulled-extensions/ directory, which may be empty if extensions were installed on a different machine.

$ swamp extension install
$ swamp datastore sync --push

Warning

Without this step, config migrate may produce an incomplete config/pulled-extensions/ tree in the remote datastore. Serve instances that hydrate from it will log "N pulled extension(s) have missing source files" and fail to load those extensions.

2. Run the migration on one instance

Pick one instance and run the config migration. This copies existing config into the datastore and sets managedConfig: true in .swamp.yaml:

$ swamp datastore config migrate

You will see output like:

[INF] cli: Set managedConfig: true in .swamp.yaml
[INF] cli: Migrated "models, workflows, vaults, lockfile, pulled-extensions" into datastore config tier
[INF] cli: Pushed config to datastore

The Pushed config to datastore line appears with a remote datastore.

The command is idempotent — running it again detects the migration sentinel and skips the copy:

$ swamp datastore config migrate --json
{ "alreadyMigrated": true, "managedConfigSet": false }

managedConfigSet is true when the run set managedConfig: true in this repository's .swamp.yaml, and false when the flag was already set.

Migrate pulls the datastore's config before it checks whether the datastore is already migrated, so the datastore must be reachable even on a repository that is already migrated.

If the push fails, migrate exits non-zero and keeps the migration locally:

The migration is saved locally but was not published to the datastore: <reason>. Run 'swamp datastore config migrate' again to publish it.

Run swamp datastore config migrate again once the datastore is reachable. The re-run publishes the migration. Do not use swamp datastore sync --push to recover: it would publish the migrated files without the migration sentinel.

Warning

Do not run config migrate on multiple instances concurrently. The migration writes index entries to the datastore, and concurrent runs can clobber each other's entries.

3. Configure other instances

Each additional instance needs managedConfig: true in its .swamp.yaml. Once the flag is set, the instance stops reading its local models, workflows and vaults and uses the ones in the datastore.

Either run the migration on the instance. It finds the datastore already migrated, skips the copy, and sets the flag:

$ swamp datastore config migrate
[INF] swamp·datastore·managed-config-migration: Config migration already completed (sentinel exists)
[INF] cli: Set managedConfig: true in .swamp.yaml
[INF] cli: Config migration already completed

Or copy the change from the first instance's .swamp.yaml:

datastore:
  type: "@swamp/s3-datastore"
  managedConfig: true
  config:
    bucket: my-bucket
    region: us-east-1

The .swamp.yaml file is the one piece of configuration that is not managed in the datastore — it is the bootstrap file and must be distributed to each instance manually (via your deployment pipeline, config management tool, or container image).

4. Restart serve instances

Restart the other swamp serve instances. On startup, each instance performs an early config pull from the datastore before loading extensions, so it starts with the latest shared config:

$ swamp serve \
    --host 0.0.0.0 \
    --auth-mode token \
    --cert-file /etc/swamp/tls/cert.pem \
    --key-file /etc/swamp/tls/key.pem

No additional flags are needed — the ConfigPoller starts automatically when managedConfig: true is set.

5. Verify config propagation

Create a model on one instance and verify it appears on another:

$ swamp model create test-model --server https://instance-a:9090
$ swamp model list --server https://instance-b:9090 --json | grep test-model

The model should appear on instance B within ~30 seconds (the default ConfigPoller interval).

Clean up the test model:

$ swamp model delete test-model --server https://instance-a:9090

How config changes propagate

Once managed config is enabled, config changes flow through two mechanisms:

  1. Immediate push. When an operative modifies config through a running instance (model create, extension pull, vault update), that instance pushes the change to the datastore immediately.
  2. ConfigPoller. Each instance polls the datastore every 30 seconds for config changes. A commitSeq fast-path skips the full pull when no changes have occurred, keeping the polling cost minimal.

The result is that config changes propagate to all instances within ~30 seconds under normal operation.

What stays local

The following are never stored in the managed config tier:

Item Reason
.swamp.yaml Bootstrap config — manual per-instance setup
Skills (.claude/skills/) Tool-specific, not shared across instances
Extension source dirs User-authored code, versioned in git
Bundles Derived artifacts, rebuilt from sources