← All migration guides

Competitor migration guide

Migrate from Bun.serve to Webship without a blind cutover.

Separate application code from edge duties: retain Bun as the origin while Webship takes over TLS, static delivery, HTTP/3, protection, and request routing.

Applies to Webship 1.1.0TypeScript

Define the migration boundary before changing traffic.

Start by moving only the behavior Webship can reproduce and validate. Leave application authentication, service discovery, scripts, and specialized cache rules on the existing origin until their replacements pass production-like tests.

Translate the smallest production path first.

The source fragment identifies the migration concept; the Webship fragment shows the target shape. Replace example domains, addresses, certificates, limits, and health paths with values validated for your environment.

Representative Bun.serve configuration
Bun.serve({
  port: 443,
  tls: { cert: Bun.file("cert.pem"), key: Bun.file("key.pem") },
  routes: {
    "/": new Response(Bun.file("./public/index.html")),
  },
});
Equivalent Webship TOML
listen = "0.0.0.0:443"
workers = 4

[[sites]]
domain = "app.example.com"
root = "/srv/app/public"
listen = "0.0.0.0:443"
cert = "/etc/letsencrypt/live/app.example.com/fullchain.pem"
key = "/etc/letsencrypt/live/app.example.com/privkey.pem"

[sites.protocols]
h1 = true
h2 = true
h3 = true

Map concepts, not syntax.

Technical directives do not always match one-to-one. Use this table to locate the equivalent Webship configuration area, then validate the effective configuration and runtime behavior.

Current concept or directiveWebship configuration target
listener / virtual hostlisten + [reverse_proxy.protocols]
document root[[sites]].root
host matcher[[reverse_proxy.routes]]
certificate and private key[reverse_proxy.tls] / [[sites]] cert + key

Use a reversible five-step cutover.

Keep the old listener ready until Webship has passed correctness, capacity, security, observability, and rollback gates on representative traffic.

  1. 1

    Inventory observable behavior

    Record listeners, domains, routes, upstreams, certificates, rewrites, authentication, cache rules, health probes, limits, and operational integrations.

  2. 2

    Translate one boundary

    Move one host or route into strict TOML. Retain vendor-specific modules and application logic behind Webship until separate replacements are proven.

  3. 3

    Validate offline and locally

    Run --check-config and --print-effective-config, inspect the redacted result, probe health locally, and exercise TLS over both TCP and UDP when HTTP/3 is enabled.

  4. 4

    Canary real traffic

    Send a small, observable traffic slice to Webship. Compare status codes, headers, bodies, latency, upstream health, cache behavior, logs, and security decisions.

  5. 5

    Promote with rollback ready

    Increase traffic in measured stages. Keep the previous target healthy and immediately routable until the agreed observation window and load gates pass.

Validate first. Roll back by routing, not by editing live.

Validate the candidate file, inspect the redacted effective configuration, and probe the private listener before changing traffic. Preserve the old binary, configuration, listener, and DNS or load-balancer target until the observation window closes.

/usr/local/bin/webship --check-config --config /etc/webship/production.toml
/usr/local/bin/webship --print-effective-config --config /etc/webship/production.toml
curl --http3-only --insecure https://127.0.0.1:443/health