Skip to content

Architecture

This page explains Stackpad’s core architecture and the mental model behind how your applications are organized and deployed.

Resource hierarchy

Organization
└── Project (services sharing a private Docker network)
├── Environment (e.g. production, staging)
│ ├── Service: web → Next.js app, exposed via HTTPS
│ ├── Service: database → PostgreSQL, internal only
│ ├── Service: cache → Redis, internal only
│ └── Service: worker → Background jobs, internal only
│ └── Deployment → A single deploy: build → container → health check
└── Environment (e.g. staging)
└── ... (same services, different containers)

Organizations

The top-level entity. An organization represents a team with a billing plan, members, and projects. All resources and costs are scoped to an organization.

Projects

A project is a stack of related services that share a private Docker network. Think of it as one application — your web frontend, database, cache, and background workers all live in one project.

Environments

Each project has one or more environments. The default environment deploys from your main branch. You can add staging environments, or enable catch-all environments for automatic preview deployments from pull request branches.

Services

A service is a single container. Services have a type that determines their default behavior:

TypeExposed externallyAuto-backupExample
WebYes (HTTPS)NoNext.js, Express
DatabaseNoYesPostgreSQL, MariaDB
CacheNoYesRedis, Valkey
ServiceNoNoWorkers, cron jobs

Deployments

A deployment is a single version of a service. When you push code or trigger a manual deploy, a new deployment is created. It goes through: queued → building → deploying → ready (or failed).

Infrastructure nodes

Stackpad’s infrastructure consists of specialized node types:

┌─────────────────────────┐
│ CONTROL NODE │
│ Caddy, API, Dashboard │
│ PostgreSQL, ClickHouse │
│ Docker Registry │
└───────────┬─────────────┘
Private Network (WireGuard)
┌─────────┼─────────┐
│ │ │
┌─┴──────┐ ┌┴──────┐ ┌┴──────┐
│ BUILD │ │COMPUTE│ │COMPUTE│
│ NODE │ │NODE 1 │ │NODE 2 │
│ Builds │ │Runs │ │Runs │
│ images │ │your │ │your │
│ │ │apps │ │apps │
└────────┘ └───────┘ └───────┘
  • Control node — runs the Stackpad platform itself: API, dashboard, reverse proxy (Caddy), database, logs
  • Build nodes — dedicated to building Docker images from your source code
  • Compute nodes — run your application containers

All nodes run on Hetzner Cloud across multiple European locations. They communicate over a private WireGuard network.

Deployment pipeline

When you push to your deployment branch:

  1. GitHub webhook → Stackpad API receives the push event
  2. Queue → deployment is queued (max 4 concurrent builds per build node)
  3. Clone → repository is cloned on the build node
  4. Detect → framework is auto-detected from package.json
  5. Build → Docker image is built using BuildKit
  6. Push → image is pushed to the private registry on the control node
  7. Pull → compute node pulls the image
  8. Start → new container starts alongside the old one
  9. Health check → Stackpad verifies the new container responds
  10. Switch → Caddy routes traffic to the new container
  11. Stop → old container is stopped

This process achieves zero-downtime deployments with automatic rollback on failure.

Reverse proxy

Caddy serves as the reverse proxy and handles:

  • HTTPS termination with automatic Let’s Encrypt certificates
  • Dynamic routing — routes are added/removed via Caddy’s admin API without restarts
  • Load balancing — traffic is routed to the correct compute node and container
  • Custom domains — CNAME and A record verification, automatic certificate provisioning

Infrastructure resilience

Stackpad is designed to survive any single server failure without affecting your services.

N+1 reserve capacity

The platform always keeps enough spare compute capacity to absorb a node going down. Before deploying, the scheduler verifies that the cluster has headroom. If reserve capacity runs low, a new compute node is provisioned automatically — before you notice.

Fast failover

When a server goes down, services recover in seconds:

  1. The health monitor detects the node failure
  2. Services are restarted from cached Docker images in the registry — no git clone or rebuild
  3. If the service has a persistent volume, the volume detaches and reattaches to the new node
  4. Recovery drops from minutes to seconds

During planned maintenance, services are gracefully drained to other nodes before the server goes offline — zero interruption.

Disaster recovery

If a container crashes or a server goes offline:

  • Automatic container recovery — crashed containers are detected and re-deployed within 60 seconds
  • Node failover — all services are migrated to a healthy node automatically
  • Restart loop detection — if a service crashes 5+ times in 10 minutes, auto-recovery is paused and your team gets an alert
  • Email alerts — your team is notified when a service has issues

Available on Pro and Business plans.

Compute auto-scaler

The platform automatically provisions extra compute capacity when needed:

  • Reactive burst provisioning — extra nodes spin up within minutes during peak deploy times
  • Automatic scale-down — idle burst nodes are removed after a cooldown period
  • Fast provisioning — new nodes are ready in under 3 minutes using pre-built golden images

Observability

Logs from all containers are collected by Vector, enriched with metadata (organization, project, service), and stored in ClickHouse for fast querying and full-text search.

What’s next?