This development guide applies to Codex, Claude Code, and OpenCode. Repository and review rules are shared through:
@AGENTS.md
E2B Infrastructure is the backend infrastructure powering E2B (e2b.dev), an open-source cloud platform for AI code interpreting. It provides sandboxed execution environments using Firecracker microVMs.
Start with docs/ARCHITECTURE.md — it explains what each service does, how services interact (with diagrams of the core flows: sandbox creation, traffic routing, pause/resume, template builds), and the deployment topology. Reading it first is the fastest way to understand this repository.
Keep docs/ARCHITECTURE.md updated: if your change alters anything it describes (service responsibilities, ports, protocols, data stores, flows, deployment topology), update the document in the same change.
# Switch between environments (prod, staging, dev)
make switch-env ENV=staging
# Setup local development stack (PostgreSQL, Redis, ClickHouse, monitoring)
make local-infra# Run all unit tests across packages
make test
# Run integration tests
make test-integration
# Build specific package
make build/api
make build/orchestrator
# Generate code (proto, SQL, OpenAPI)
make generate
# Format and lint code
make fmt
make lint
# Regenerate mocks
make generate-mocks
# Tidy go dependencies
make tidy# From packages/api/
make run-local # Run API server on :3000
make dev # Run with air (hot reload)
# From packages/orchestrator/
make run-local # Run orchestrator
make run-debug # Run with race detector# API: Generate OpenAPI code
cd packages/api && make generate
# Orchestrator: Generate proto + OpenAPI
cd packages/orchestrator && make generate
# DB: Run migrations
make migrate
# Run single test
cd packages/<package> && go test -v -run TestName ./path/to/package# Build and upload all service images to your GCP project
make build-and-upload
# Build specific service
make build-and-upload/api
make build-and-upload/orchestratorClient → Client-Proxy → API (REST) ⟷ PostgreSQL
↓ ⟷ Redis
Orchestrator ⟷ ClickHouse
↓ (gRPC)
Firecracker VMs
↓
Envd (in-VM daemon)
API (packages/api/) - REST API using Gin framework
- Entry point:
main.go - Core logic:
internal/handlers/store.go(APIStore) - Authentication: API keys and OIDC auth provider JWTs
- OpenAPI code generation:
internal/api/*.gen.go - Port: 80
Dashboard API (packages/dashboard-api/) - REST backend for the web dashboard, not the SDK
- Entry point:
main.go - Spec:
spec/openapi-dashboard.yml; legacy team management, template tags, builds, admin bootstrap,/v1/management - Talks to Postgres and ClickHouse; never to orchestrators (see
docs/ARCHITECTURE.md) - Port: 3010
Orchestrator (packages/orchestrator/) - Firecracker microVM orchestration
- Entry point:
main.go - VM management:
pkg/sandbox/ - Firecracker integration:
pkg/sandbox/fc/ - Networking:
pkg/sandbox/network/ - Storage:
pkg/sandbox/nbd/(Network Block Device) - Template caching:
pkg/sandbox/template/ - Template building:
pkg/template/ - gRPC server:
pkg/server/ - Utilities:
cmd/clean-nfs-cache/,cmd/inspect-build/,cmd/dummy-orchestrator/
Envd (packages/envd/) - In-VM daemon using Connect RPC
- Runs inside each Firecracker VM
- Process management API:
packages/envd/spec/process/process.proto - Filesystem API:
packages/envd/spec/filesystem/filesystem.proto - Port: 49983
- Version in
pkg/version.gomust be bumped on every behavioral change (not comments/docs-only changes)
Client Proxy (packages/client-proxy/) - Edge routing layer
- Service discovery via
packages/shared/pkg/servicediscovery - Request routing to orchestrators
- Redis-backed state management
Shared (packages/shared/) - Common utilities
- Proto definitions:
pkg/grpc/orchestrator/,pkg/grpc/envd/ - Telemetry:
pkg/telemetry/(OpenTelemetry) - Logging:
pkg/logger/(Zap + OTEL) - Database:
pkg/db/(ent ORM) - Models:
pkg/models/ - Storage:
pkg/storage/(GCS/S3 clients) - Feature flags:
pkg/featureflags/(LaunchDarkly)
Database (packages/db/) - PostgreSQL layer
- Migrations:
migrations/*.sql(goose) - Queries:
queries/*.sql(sqlc) - Generated code:
queries/(pluspkg/auth/queries/,pkg/dashboard/queries/)
- go 1.26.8 with workspaces (
go.work) - Firecracker for microVM virtualization
- PostgreSQL for primary data (sqlc for queries)
- ClickHouse for analytics
- Redis for caching and state
- OpenTelemetry for observability (Grafana stack: Loki, Tempo, Mimir)
- gRPC/Connect RPC for service communication
- Gin (API), chi (Envd) for HTTP
The codebase uses several code generators:
-
Protocol Buffers (
packages/orchestrator/generate.Dockerfile)- Generates:
packages/shared/pkg/grpc/*/ - Run:
make generate/orchestrator
- Generates:
-
OpenAPI (
oapi-codegen)- Spec:
spec/openapi.yml - Generates: API handlers, types, specs
- Run:
make generate/api
- Spec:
-
SQL (
sqlc)- Queries:
packages/db/queries/*.sql - Generates: Type-safe DB code
- Run:
make generate/db
- Queries:
-
Mocks (
mockery)- Config:
.mockery.yaml - Run:
make generate-mocks
- Config:
- Unit tests: Use
testify/assertandtestify/require - Database tests: Use
testcontainers-gofor real PostgreSQL - Integration tests:
tests/integration/with shared test utilities - Mocking: Generated mocks in
mocks/directories - Race detection: Tests run with
-raceflag
Example test invocation:
# Single package
go test -race -v ./internal/handlers
# Specific test
go test -race -v -run TestCreateSandbox ./internal/handlers- Proto files:
packages/envd/spec/process/,packages/envd/spec/filesystem/, orchestrator protos atpackages/orchestrator/*.proto - Shared protos:
packages/shared/pkg/grpc/ - After editing proto files, run
make generate/orchestratorandmake generate/shared
- Migrations:
packages/db/migrations/ - Create:
cd packages/db && make create-migration NAME=your-migration-name— this generates the file with a correctYYYYMMDDHHMMSStimestamp. Do NOT hand-create migration files; placeholder timestamps like120000/000000cause same-day version collisions and are rejected by the out-of-order-migrations CI check. - Apply:
make migrate(requires POSTGRES_CONNECTION_STRING) - Code generation:
make generate/db(regenerates sqlc code)
- Local development defaults:
packages/<service>/.env.local; see DEV-LOCAL.md. - Self-hosting configuration: embed/compose/.env; see embed/README.md.
- Custom environment configs:
.env.<environment>, selected withmake switch-env ENV=<environment>.
- Orchestrator requires sudo to run (Firecracker needs root)
- VM networking uses
iptablesand Linuxnetlink - Storage uses NBD (Network Block Device)
- Templates cached in GCS bucket (configurable via TEMPLATE_BUCKET_NAME)
- Kernel/Firecracker versions:
packages/fc-versions/
- All services export OpenTelemetry traces/metrics/logs
- Local stack includes Grafana + Loki + Tempo + Mimir
- Telemetry setup:
packages/shared/pkg/telemetry/ - Logger:
packages/shared/pkg/logger/(Zap with OTEL) - Profiling: API exposes pprof on
/debug/pprof/(seepackages/api/Makefileprofiler target)
.github/workflows/pull-request.yml- PR orchestrator (lint, OpenAPI, unit, arm64, integration).github/workflows/pr-tests.yml- Unit test shards.github/workflows/integration_tests.yml- Integration test suite
- Service Isolation: Each service runs in containers with defined gRPC/HTTP interfaces
- Shared Libraries: Cross-cutting concerns (logging, telemetry, DB) in
packages/shared - Event-Driven: ClickHouse + Redis pub/sub for async operations
- Caching Strategy: Redis for templates, auth tokens, performance optimization
- Feature Flags: LaunchDarkly for gradual rollouts
- Graceful Shutdown: Services handle SIGTERM with context cancellation
- Health Checks: gRPC health protocol + HTTP health endpoints
- Local: Docker logs in
make local-infra - Production: Grafana Loki