Overview
Every user project in Tesslate Studio runs in an isolated containerized environment. Projects can have multiple containers (frontend, backend, database) that communicate over a private network. The orchestration layer manages container lifecycle, file operations, shell execution, resource management, and cleanup. This page covers both deployment modes (Docker and Kubernetes), the factory pattern that abstracts them, the S3 Sandwich pattern for hibernation, the EBS VolumeSnapshot lifecycle, pod affinity for multi-container projects, and the cleanup CronJob.The Factory Pattern
All code accesses the orchestrator through a factory function. The factory readsconfig.DEPLOYMENT_MODE and returns the appropriate implementation.
BaseOrchestrator Interface
Both implementations conform to the same abstract interface:Docker Mode (Local Development)
Architecture and Configuration
Architecture and Configuration
Source file:
orchestrator/app/services/orchestration/docker.pyDocker mode uses Docker Compose to manage user projects. Each project gets:- A dedicated Docker network for isolation
- Services defined in a dynamically generated
docker-compose.yml - Traefik routing for
*.localhostURLs - Direct filesystem access via shared volume (
/projects)
- Fast iteration with no cluster overhead
- Simple file operations (orchestrator reads the filesystem directly)
- Traefik auto-discovery via container labels
- Two-tier cleanup: scale to 0, then delete after longer timeout
http://{project-slug}-{container-name}.localhostConfiguration:Docker Mode: How It Works
Generate docker-compose.yml
The orchestrator generates a Compose file from the project’s Container models. Each container becomes a service with the correct image, ports, volumes, and Traefik labels.
Start with docker-compose up
The generated file is executed with
docker-compose up -d. Containers start in the background.Traefik routes requests
Traefik discovers containers via labels and routes
*.localhost URLs to the correct container ports.File operations: direct filesystem
The orchestrator reads and writes files directly on the host filesystem at
users/{user_id}/{project_slug}/. No pod exec required.Kubernetes Mode (Production)
Architecture and Configuration
Architecture and Configuration
Source file:
orchestrator/app/services/orchestration/kubernetes_orchestrator.pyKubernetes mode creates a namespace per project with:- PersistentVolumeClaim (PVC) for file storage
- File-manager pod (always running for file operations)
- Dev container pods (started on-demand)
- NetworkPolicy for project isolation
- NGINX Ingress for HTTPS routing
- Scalable to thousands of concurrent projects
- EBS VolumeSnapshot pattern for near-instant hibernation and restore
- Pod affinity for shared RWO storage in multi-container projects
- S3 credentials never exposed to user pods
https://{project-slug}-{container-directory}.{domain}Configuration:Three Separate Lifecycles
A critical design principle in Kubernetes mode is the separation of three distinct lifecycles:File Lifecycle
- User opens project; namespace + PVC + file-manager pod created.
- User adds container to graph; file-manager runs
git cloneto/app/{subdir}/. - Files persist on PVC.
Container Lifecycle
- User clicks “Start”; Deployment + Service + Ingress created.
- Dev container mounts existing PVC (files already present; no init containers).
- User clicks “Stop”; Deployment deleted, files remain on PVC.
Snapshot Lifecycle
- User leaves or idle timeout; VolumeSnapshot created from PVC (under 5 seconds).
- Namespace deleted (including PVC).
- User returns; PVC created from snapshot, EBS lazy-loads data (near-instant restore).
File-Manager Pod
The file-manager pod is always running while a project is open.| Property | Value |
|---|---|
| Image | tesslate-devserver:latest |
| Command | tail -f /dev/null (keep alive) |
| Volume | PVC mounted at /app |
| Resources | 256Mi to 1536Mi RAM |
- Handle file read/write when dev containers are not running
- Execute
git clonewhen containers are added to the architecture graph - Keep PVC mounted to prevent unbound state
- Provide consistent file access regardless of dev container state
Dev Container Pods
Dev containers are created on-demand when the user clicks “Start.”Read TESSLATE.md configuration
The orchestrator reads
TESSLATE.md from the file-manager pod to determine port, startup command, and framework.Create Deployment
Image:
tesslate-devserver:latest. Volume: existing PVC at /app. Working directory: /app/{container_directory}. Command: startup command runs in a tmux session.Create Service and Ingress
ClusterIP service with selector by container-id. NGINX Ingress with TLS using the wildcard certificate.
EBS VolumeSnapshot Lifecycle
The EBS VolumeSnapshot pattern hibernates idle projects to save compute resources while preserving the full filesystem state (includingnode_modules).
Snapshot Operations
| Operation | What Happens |
|---|---|
| Create | VolumeSnapshot created from PVC. Non-blocking; poll until readyToUse: true. ProjectSnapshot database record created. |
| Restore | PVC created with dataSource pointing to VolumeSnapshot. EBS provisioner creates new volume from snapshot with lazy-loading. |
| Soft-delete | When a project is permanently deleted, snapshots are marked for 30-day retention. |
| Permanent delete | Daily cleanup CronJob deletes expired snapshots after 30 days. |
Timeline UI
Users can create up to 5 manual snapshots per project for version history, accessible through the Timeline UI. Each snapshot preserves the entire filesystem state and can be restored at any time.S3 Sandwich Pattern (Legacy / Fallback)
For environments without VolumeSnapshot support (e.g., Minikube), the S3 Sandwich pattern provides an alternative:Hydration (project start)
Init process downloads the project archive from S3 to the PVC. Fast local I/O resumes.
Pod Affinity for Multi-Container Projects
When a project has multiple containers (e.g., frontend + backend), all pods must run on the same Kubernetes node because PVCs useReadWriteOnce (RWO) access mode.
project-id label land on the same node, enabling shared RWO volume access and improving inter-container communication performance.
NetworkPolicy Isolation
Each project namespace receives a NetworkPolicy that enforces:- Allowed ingress: From NGINX Ingress controller, from Tesslate backend (file operations), within the namespace (inter-container)
- Allowed egress: DNS (UDP 53), HTTPS (TCP 443), HTTP (TCP 80)
- Denied: All cross-project communication, access to internal cluster services not explicitly allowed
Cleanup CronJob
Two Kubernetes CronJobs manage automatic cleanup:- Hibernation CronJob
- Snapshot Cleanup CronJob
Schedule: Every 2 minutes (
*/2 * * * *)Queries the database for projects where environment_status = 'active' and last_activity is older than the idle timeout (default: 30 minutes). For each idle project:- Creates a VolumeSnapshot
- Deletes the namespace
- Updates the database status to “hibernated”
- Sends a WebSocket notification to redirect the user
Debugging Commands
- Docker Mode
- Kubernetes Mode
Key Source Files
| File | Purpose |
|---|---|
orchestrator/app/services/orchestration/base.py | Abstract orchestrator interface |
orchestrator/app/services/orchestration/factory.py | Factory pattern and mode detection |
orchestrator/app/services/orchestration/docker.py | Docker Compose orchestrator |
orchestrator/app/services/orchestration/kubernetes_orchestrator.py | Kubernetes orchestrator |
orchestrator/app/services/orchestration/kubernetes/client.py | K8s API wrapper |
orchestrator/app/services/orchestration/kubernetes/helpers.py | Manifest generation functions |
orchestrator/app/services/snapshot_manager.py | EBS VolumeSnapshot operations |
orchestrator/app/services/s3_manager.py | S3 hydration/dehydration |
orchestrator/app/services/activity_tracker.py | Database-based activity tracking |