Signadot Sandboxes
Signadot Sandboxes provide isolated, logical environments within the stage Kubernetes cluster for testing PR changes. Each sandbox contains only the changes from a specific PR and interacts with existing cluster resources through request routing and context propagation.
When to use this skill
- Setting up or debugging a Signadot sandbox for a PR
- Configuring context propagation (
ot-baggage-bitsoheader) - Integrating message isolation (Kafka, SQS, SNS) in a Java service
- Testing across multiple sandboxes with route groups
- Troubleshooting sandbox routing or message filtering issues
- Understanding caveats around shared datastores and background jobs
- Working with sandbox YAML specs, templates, or CI/CD automation
Skill Contents
Sections
- Quick Start
- Sandbox Lifecycle
- Sandbox CLI Management
- Context Propagation
- Message Isolation
- Route Groups
- Key Caveats
- Related
Available Resources
- caveats and mitigations
- context propagation
- message isolation kafka
- message isolation sns redis
- message isolation sqs
- route groups and multi sandbox
- sandboxes overview
- signadot dashboard
- testing guide
Quick Start
Browser testing
Install the Signadot browser extension to auto-inject routing keys, or use ModHeader to manually set the ot-baggage-bitso header.
cURL
curl -H 'ot-baggage-bitso: <routing-key>' https://stage.example.com/api/endpoint
gRPC (via bitso env connect)
bitso env connect
grpcurl -H 'baggage: sd-routing-key=<routing-key>' \
service.stage.svc.cluster.local:8201 my.Service/Method
Finding your routing key
- PR comments -- The
Signadot botposts the routing key when the sandbox is created - Signadot dashboard -- At app.signadot.com/sandboxes
- Signadot CLI --
signadot sandbox get <sandbox-id>
Sandbox Lifecycle
Sandboxes are created automatically when a PR is opened in a repository with Signadot enabled in the Estate Catalogue (sandbox: true in the .cue file). The sandbox:
- Creates after a successful build with new Docker images
- Deploys forked services, CronJobs, and ConfigMaps on the stage cluster
- Names itself as
<repo-name>-<pr-number>(e.g.,stocks-416) - Provides a unique routing key for traffic isolation
- Updates automatically when new commits are pushed to the PR
- Deletes automatically when the PR is closed/merged, or after 48h TTL
For full details on creation, deletion, and EC enablement, see sandboxes overview.
Sandbox CLI Management
Create or update a sandbox
Write a YAML spec file and apply it:
name: my-sandbox
spec:
cluster: stage
description: Testing new feature
forks:
- forkOf:
kind: Deployment
namespace: stage
name: my-app
customizations:
images:
- image: example.com/my-app:dev-abcdef
container: my-app
env:
- name: FEATURE_FLAG
container: my-app
operation: upsert
value: "true"
defaultRouteGroup:
endpoints:
- name: my-endpoint
target: http://my-app.stage.svc:8080
signadot sandbox apply -f my-sandbox.yaml
Templates
Use @{variable} directives, expanded at apply time with --set:
signadot sandbox apply -f sandbox-template.yaml \
--set dev=jane --set cluster=stage --set tag=pr-42-abc123
Template features: @{variable} (string), @{embed: file.txt} (inline file), @{var[yaml]} (YAML expansion).
List, get, delete
signadot sandbox list
signadot sandbox get my-sandbox -o json
signadot sandbox delete my-sandbox
TTL (auto-deletion)
spec:
ttl:
duration: "2h"
offsetFrom: createdAt
CI/CD patterns
# Create sandbox per PR
signadot sandbox apply -f sandbox.yaml \
--set name="pr-${PR_NUMBER}" --set tag="${COMMIT_SHA}"
# Clean up on PR close
signadot sandbox delete "pr-${PR_NUMBER}"
Context Propagation
Signadot uses header-based context propagation to route requests through sandboxed services. At Bitso, the OpenTracing baggage format is used:
- Header:
ot-baggage-bitso - Value: The sandbox routing key (e.g.,
zx4ygbjd5k4s4)
Datadog libraries automatically propagate this header across HTTP and gRPC calls for Java services. No code changes are needed for most services.
Key points:
- For services without OpenTelemetry SDK: DD Trace Agent forwards
ot-baggage-bitsotransparently - For services with OpenTelemetry SDK: Custom configuration needed (see BFF services example)
- W3C Baggage format (
baggage: sd-routing-key=<key>) is supported only for OTel-instrumented services
For Spring Boot examples (HTTP filters, gRPC interceptors) and verification via Datadog, see context propagation.
Message Isolation
Shared messaging infrastructure (Kafka, SQS, SNS) requires explicit isolation to prevent cross-contamination between sandbox and baseline.
Kafka
Library: com.bitso.aws.msk:msk-client
- Consumer side:
SignadotFilterStrategyfilters messages by routing key inot-baggage-bitsoheader - Producer side:
SignadotKafkaProducerFactoryinjects routing keys viaRoutingKeyContext - Consumer groups: Append
${signadot.sandbox.consumer-group-suffix}to all group IDs
See message isolation kafka for complete integration guide.
SQS
Library: com.bitso.aws.sqs:sqs-client
- Auto-configured via Spring Boot for stage/local environments
- Uses extractor chain: AWSTraceHeader > DirectAttribute > SnsMessageBody
- Producer side:
SignadotSqsClientDecoratorwraps SQS clients via bean post-processor
See message isolation sqs for details.
SNS and Redis Streams
- SNS: DD Java agent auto-instruments SNS publish calls; downstream SQS filtering handles isolation
- Redis Streams: No header support; use dedicated test topics for sandbox testing
See message isolation sns redis.
Route Groups
Route groups combine multiple sandboxes into a single routing context for cross-repo testing. RISE (Release Integration Sandbox Engine) automatically creates a route group for each PR, matching on the branch label.
To test across repos: Use the same branch name in each PR. All matching sandboxes join the same route group automatically.
Route group CLI management
signadot routegroup apply -f my-routegroup.yaml
signadot routegroup list -o json
signadot routegroup get my-routegroup
signadot routegroup delete my-routegroup
Match criteria
- Single label:
match.label: {key: "k", value: "v"} - Any (OR):
match.any: [{label: ...}, ...] - All (AND):
match.all: [{label: ...}, ...] - Values support glob patterns:
value: "feature-*"
For details on label matching and examples, see route groups and multi-sandbox.
Key Caveats
Sandboxes share the stage cluster's datastores and infrastructure. Be aware of:
| Area | Risk | Mitigation |
|------|------|------------|
| Routing | Header dropped at a hop | Ensure all edges forward ot-baggage-bitso |
| Caching | Cache pollution across envs | Disable cache or prefix keys with routing key |
| Databases | Shared Postgres/Redis writes | Disable migrations in sandbox; use scoped writes |
| Background jobs | Duplicate processing | Disable schedulers in sandbox profile |
| External APIs | Payments, emails, webhooks | Use test accounts/stubs |
| Istio | VirtualServices not mesh-aware | Test Istio changes in DEV cluster |
When NOT to use sandboxes: Operations that mutate shared global state (permission migrations, destructive backfills). Use the development cluster instead.
For Spring Boot sandbox profile examples and full mitigation guide, see caveats and mitigations.
Related
- signadot-local-dev skill -- Local development with Bitso CLI and Signadot Local
- signadot-mcp skill -- AI-assisted sandbox management via MCP
- Signadot official docs
- Bitso Sandboxes Confluence