SHARDWIRE
Guides

Incremental adoption

Move from a monolithic discord.js bot to Shardwire in stages: events-only sidecar, then actions, then multiple scoped app processes—without rewriting everything on day one.

Shardwire’s split is a process boundary, not a requirement to delete your existing bot on the first commit. This guide describes a default happy path used by teams that already ship a single discord.js codebase and want to adopt Shardwire safely.

  • Bot process: createBotBridge() owns the Discord client, intents, and bridge server. It stays the only place that touches DISCORD_TOKEN for gateway traffic.
  • App process(es): connectBotBridge() over ws:// (local) or wss:// (remote), each with a manifest, strict startup where appropriate, and a scoped secret when more than one consumer exists.

Read How Shardwire works if you have not internalized that split yet.

Stage A — Events-only sidecar (lowest risk)

Goal: Keep command handlers and most logic in the monolith; mirror one event stream to a separate process for logging, metrics, or experimentation.

  1. Add a small Node process that calls connectBotBridge() with the same secret you already use for local tooling (or add a new scoped secret that only allows events you need—see Capabilities & scoped secrets).
  2. In the bot process, introduce createBotBridge() alongside your existing client, or migrate gateway ownership in one controlled step (many teams replace client.login() flow with createBotBridge().ready() once secrets and ports are ready—see Bot bridge).
  3. Subscribe only to read-only events first (for example messageCreate without moderation actions on the app side).

Contract: Define a minimal manifest with only those events (and no actions if the app is read-only). Use defineShardwireApp and pass it to app.ready({ strict: true, manifest, botIntents }) so mismatched intents or subscriptions fail at startup instead of at runtime.

Exit: App process receives normalized payloads and you are comfortable with deployment (URLs, secrets, restarts).

Stage B — Actions on the app process

Goal: Move specific side effects (delete message, timeout member, follow-up to an interaction) into the app process while the bot process remains the Discord gateway host.

  1. Extend the manifest with the actions the app will call.
  2. Regenerate or adjust the bot secrets entry using generateSecretScope (or a slightly wider manual allow list) so negotiation includes those actions.
  3. Every action call should branch on result.ok (App bridge).

Optional: set expectedScope in strict startup so a deployment mistake cannot silently grant more than the manifest implies.

Exit: One vertical slice (for example “automod delete + log”) runs through the bridge with typed results.

Stage C — Multiple app consumers

Goal: Separate teams or services (dashboard, moderation worker, analytics) each get their own secret and capability surface.

  1. Add multiple entries under server.secrets on the bot bridge (Bot bridge).
  2. Give each app process its own secret value and manifest. Prefer narrow allow.events / allow.actions per secret (Capabilities & scoped secrets).
  3. Use strict startup per app so each process validates its contract against negotiation.

Exit: Adding a new dashboard does not force widening the moderation worker’s secret.

What not to do in early stages

  • Do not treat the manifest as a full application config file—it is only the app contract (Manifests).
  • Do not register app.on handlers after await app.ready({ strict: true }) and expect them to be covered by strict startup’s subscription snapshot; register handlers first, then call ready.

Where to go next

  • Manifests and Strict startup for contracts.
  • Diagnostics and formatShardwireDiagnosis (see reference) for readable reports in logs and CI.
  • Recipe pages under Guides for end-to-end shapes (moderation, interactions, analytics-only).

On this page