Sandbox Environments
Pattern for isolated, developer-owned sandbox environments for local development and testing.
Definition
A sandbox is an isolated, non-production environment designed for:
- Local development
- Experimentation
- Testing
- Debugging
Sandboxes are developer-owned and MUST NOT affect production systems, data, or resources.
Core Principles
Isolation
Sandboxes MUST be completely isolated from production:
- No access to production databases
- No access to production APIs (unless explicitly read-only and safe)
- No ability to trigger production events or side effects
- No shared state with production systems
Developer Ownership
Each developer MUST be able to:
- Start their own sandbox independently
- Tear down their sandbox without coordination
- Modify sandbox configuration without affecting others
- Run multiple sandboxes simultaneously if needed
Reproducibility
Sandboxes MUST be:
- Quickly recreatable from scratch
- Consistent across different developer machines
- Documented in the repository's operational instructions
Sandbox Architectures
Sandboxes may take different forms depending on the repository:
Local-Only Sandbox
All components run on the developer's machine:
- Databases: Docker Compose or local instances
- Services: Running natively or in containers
- External dependencies: Mocked or stubbed
When to use: Simple services with minimal external dependencies
Hybrid Sandbox
Mix of local and remote resources:
- Frontend: Running locally for fast iteration
- Backend: Running locally or against a shared dev environment
- Databases: Local or remote development instances
- External APIs: Mocked locally or pointing to dev endpoints
When to use: Complex systems with heavy infrastructure requirements
Remote Sandbox
Ephemeral cloud resources:
- Infrastructure: Deployed to a dedicated sandbox namespace
- Databases: Isolated sandbox instances
- Services: Deployed to sandbox environment
- Cleanup: Automated teardown after session
When to use: Services requiring production-like infrastructure
Requirements
Task Exposure
If a repository CAN reasonably run in sandbox mode, it MUST provide Taskfile tasks:
sandbox:start— Start the sandbox environmentsandbox:stop— Stop and clean up the sandboxsandbox:restart— Restart the sandbox environmentsandbox:seed— Seed the sandbox environment with sample datasandbox:reset— Reset sandbox to clean state (optional)
If a repository CANNOT run in sandbox mode (e.g., infrastructure-only repos), this MUST be documented in AGENTS.md.
No Production Leakage
Sandboxes MUST implement safeguards:
- Environment variables clearly distinguish sandbox from production
- Configuration defaults to sandbox mode
- Accidental production access is prevented by design
Example environment variable naming:
# Clear distinction
SANDBOX_MODE=true
ENVIRONMENT=sandbox
# Avoid ambiguous naming
ENV=dev # Unclear if this is sandbox or shared dev
Easy Teardown
Developers MUST be able to:
- Tear down sandboxes without manual cleanup
- Remove all sandbox resources with a single command
- Avoid orphaned resources (containers, volumes, cloud resources)
Sandbox vs. Other Environments
| Environment | Purpose | Isolation | Longevity | Data |
|---|---|---|---|---|
| Sandbox | Dev/experimentation | Complete | Ephemeral | Disposable |
| Development | Integration testing | Shared | Persistent | Realistic but not real |
| Staging | Pre-production validation | Production-like | Persistent | Production snapshot |
| Production | Real users | Complete | Permanent | Real data |
Anti-Patterns
❌ Shared "Dev" Databases
Multiple developers sharing a single development database:
- Causes state conflicts between developers
- Makes debugging harder
- Slows down development
Instead: Each developer runs their own isolated database in their sandbox.
❌ Manual Setup Steps
Requiring developers to manually provision resources:
- Increases friction and setup time
- Leads to inconsistent environments
- Makes onboarding painful
Instead: Automate sandbox startup with sandbox:start.
❌ Stateful Sandboxes
Sandboxes that accumulate state over time:
- Become unreproducible
- Drift from clean state
- Hide bugs that only appear in fresh environments
Instead: Design sandboxes to be easily reset to a known good state.
❌ Production Credentials in Sandbox
Using production API keys or credentials in sandbox:
- Risks accidental production modifications
- Violates least privilege principle
- Creates security exposure
Instead: Use sandbox-specific credentials or mocks.
Examples
Simple Sandbox (Local Docker)
# Taskfile.yaml
sandbox:start:
desc: Start local sandbox environment
cmds:
- docker compose -f docker-compose.sandbox.yml up -d
- task: dev:migrate
- echo "Sandbox running at http://localhost:8080"
sandbox:stop:
desc: Stop and clean up sandbox
cmds:
- docker compose -f docker-compose.sandbox.yml down -v
Hybrid Sandbox (Local Frontend + Remote Backend)
# Taskfile.yaml
sandbox:start:
desc: Start hybrid sandbox (local frontend + dev backend)
cmds:
- echo "Starting frontend locally..."
- npm run dev &
- echo "Frontend: http://localhost:3000"
- echo "Backend: https://api-dev.ontopix.internal"
sandbox:stop:
desc: Stop local frontend
cmds:
- pkill -f "npm run dev"
Remote Sandbox (Ephemeral Cloud)
# Taskfile.yaml
sandbox:start:
desc: Deploy ephemeral sandbox to cloud
vars:
SANDBOX_ID:
sh: echo "sandbox-$(whoami)-$(date +%s)"
cmds:
- terraform -chdir=.infra/sandbox apply -var="sandbox_id={{.SANDBOX_ID}}"
- echo "Sandbox deployed: {{.SANDBOX_ID}}"
sandbox:stop:
desc: Destroy ephemeral sandbox
cmds:
- terraform -chdir=.infra/sandbox destroy -auto-approve
Sandbox-Specific Configuration
Configuration SHOULD default to sandbox mode:
# config.py
import os
ENVIRONMENT = os.getenv("ENVIRONMENT", "sandbox") # Default to sandbox
DATABASE_URL = os.getenv(
"DATABASE_URL",
"postgresql://localhost:5432/myapp_sandbox" # Sandbox default
)
if ENVIRONMENT == "production":
# Production overrides
DATABASE_URL = os.getenv("PROD_DATABASE_URL") # No default for production
Documentation Requirements
Every repository with sandbox capability MUST document in AGENTS.md:
- How to start the sandbox
- What the sandbox includes (databases, services, etc.)
- How to verify the sandbox is working
- How to tear down the sandbox
- Any prerequisites (Docker, cloud CLI, etc.)
Example:
## Sandbox Mode
This repository supports local sandbox mode using Docker Compose.
**Start sandbox:**
task sandbox:start
**Sandbox includes:**
- PostgreSQL database (port 5432)
- Redis cache (port 6379)
- API service (port 8080)
**Verify sandbox:**
curl http://localhost:8080/health
**Stop sandbox:**
task sandbox:stop
**Prerequisites:**
- Docker and Docker Compose installed
- Ports 5432, 6379, 8080 available
Related Patterns
- Taskfile as Contract — Exposing sandbox operations
- Repository Structure — Where sandbox config lives
- AI Agent Entrypoint — How agents use sandboxes
Rationale
Sandboxes exist to:
- Enable fearless experimentation
- Reduce developer setup time
- Prevent accidental production impact
- Make development environments reproducible
Isolated, developer-owned sandboxes are a prerequisite for productive development at Ontopix.
Repository Structure
Pattern defining minimum required files and directory conventions for Ontopix repositories.
Taskfile as Contract
Pattern for using Taskfile as the single operational interface for repository operations, with prescriptive task naming, CI namespace, environment handling, and recipes.