Skip to content
Esc
navigateopen⌘Jpreview
On this page

Quickstart

Build, test, deploy, and serve your first Switchboard rule in five minutes, no object store required.

This tutorial takes you from an empty directory to a running proxy that hot-reloads your rule. It uses the file:// registry, so there is nothing to provision.

Prerequisites

  • Go 1.22+: rules are plain Go packages.
  • TinyGo: compiles rules to WebAssembly. Install it from the TinyGo guide.
  • The Switchboard CLI:
go install github.com/ethndotsh/switchboard/cmd/switchboard@latest

Build and deploy a rule

Scaffold a project

switchboard init creates a rule project with a working rule, a test suite, and a config file:

mkdir my-rules && cd my-rules
switchboard init --name my-rules --registry file://./registry
  • go.mod
  • switchboard.yaml
  • rules/
    • basic/
      • rule.go
      • tests.yaml

Look at the rule

A rule is one exported function. switchboard build generates the Wasm wrapper around it, so the package stays plain Go:

package basic

import "github.com/ethndotsh/switchboard/sdk"

func Handle(req sdk.Request) sdk.Action {
	if req.Path() == "/blocked" {
		return sdk.Deny(403).WithReason("blocked-path")
	}

	return sdk.Next().SetRequestHeader("x-powered-by", "switchboard")
}

Build and test the bundle

build compiles the rule with TinyGo and embeds tests.yaml into the bundle. test runs the bundle against its own behavioral contract:

switchboard build
switchboard test

You can also poke at it interactively with one-off requests:

switchboard eval --method GET --path /blocked
decision:  deny
reason:    blocked-path
status:    403

Deploy it

deploy uploads the bundle to the registry and repoints the prod channel at it, recording an immutable revision:

switchboard deploy

Serve traffic through it

Start the standalone proxy against any upstream (swap in whatever you have listening locally):

switchboard serve --listen :8080 --upstream localhost:3000 \
  --registry file://./registry --channel prod
curl -i localhost:8080/blocked      # 403 from your rule
curl -i localhost:8080/anything     # proxied, with x-powered-by: switchboard

Change the rule live

Edit rules/basic/rule.go — say, block another path:

func Handle(req sdk.Request) sdk.Action {
	if req.Path() == "/blocked" {
		return sdk.Deny(403).WithReason("blocked-path")
	}
	if req.Path() == "/internal" { 
		return sdk.Deny(404).WithReason("internal-path") 
	} 

	return sdk.Next().SetRequestHeader("x-powered-by", "switchboard")
}
switchboard build && switchboard deploy

Within the poll interval (2 seconds by default) the running proxy downloads, verifies, tests, and atomically activates the new bundle, with no restart. If you break something:

switchboard rollback --channel prod

Where the defaults came from

switchboard init wrote a switchboard.yaml that every command reads its defaults from, so build, deploy, and friends work with no flags:

name: my-rules
rule: ./rules/basic
dist: ./dist
channel: prod
registry: file://./registry

See the configuration reference for every field.

Next steps

Last updated on July 17, 2026

Was this page helpful?