8.6 Building, bundling, and deploying (rs2 deploy)
Deploying a custom service is a two-stage idea: upload the code (it's stored content-addressed and immutable), then mount it by reference. This section covers getting the bytes onto the node; 8.7 covers mounting and versioning.
JavaScript: bundle then upload
Your source can import dependencies, but the runtime won't resolve modules at
runtime (8.3) — so you bundle to a single ES module first. rs2 deploy --bundle
does both steps:
rs2 deploy service.ts --name my-svc --bundle
--bundle runs npx esbuild service.ts --bundle --format=esm --platform=browser
(the same settings the compat layer is tested against), then uploads the result.
npm deps resolve at build time; native addons fail there (the right place to find
out). Node.js must be on PATH for this.
Without --bundle, deploy uploads the file as-is (use it when you've already
bundled).
WebAssembly: build then upload
cargo build --target wasm32-wasip2 --release
rs2 deploy target/wasm32-wasip2/release/my_svc.wasm --name my-svc
The CLI detects the type by content: .js/.mjs deploy as JS bundles; \0asm
files as components.
Targeting a server
rs2 deploy service.ts --name my-svc --bundle `
--server http://127.0.0.1:3100/services `
--token $adminToken
--server defaults to http://127.0.0.1:3100/services; --token adds a bearer
header for a protected services mount (the deploy goes through the self-config
API, so it's gated by that mount's write access — operators only, 5.0).
The raw HTTP equivalent
rs2 deploy is a convenience over the services code store (Part 10). Under the
hood it's:
POST /services/code/my-svc/ Content-Type: application/javascript | application/wasm
→ 201 + Location + { name, version, ref, validated }
The response gives you the immutable ref — code:my-svc@<version> — which
you'll use to mount it.
You can attach an optional discovery manifest at deploy time with the
X-RS2-Manifest header. It declares inputSchema, outputSchema, effect and
media types (and optionally a store pattern), so a custom mount appears in the
agent surface and OpenAPI with a useful contract instead of as an opaque action.
The manifest is stored beside the bundle but does not change its content hash.
See 8.11 for the shape.
The compile smoke test
On upload, the server runs a compile smoke test when the matching engine is
in its build: a broken bundle is rejected with 502 contract_violation (with the
JS exception or compile error included), so bad code never becomes a deployable
version. Identical bytes always produce the identical version (content-addressed).
Validate before you ship
rs2 test <projectDir> checks the manifest and component locally before you
deploy — a faster loop than discovering problems at upload. Use it as your
pre-deploy gate.
With the bytes uploaded and a ref in hand, the next section mounts the service
and explains versioning and rollback.
← Previous: 8.5 Capability grants · Manual home · Next: 8.7 Versioning, rollback, mounting →