DeploxaDeploxa/Docs
Back to site
  • Overview
  • How It's Built
  • Quick Start
  • Frameworks
  • Deployments
  • Custom Domains

Engineering

How it's built

Deploxa is a deployment platform built as three cooperating services. This page is the honest engineering tour — the real architecture, the trade-offs, and what's production-tested versus a reference implementation.

Context

This is a portfolio project, not a commercial product. The AWS path is exercised end-to-end; the other cloud providers are reference implementations of the same interfaces (more on that below). Nothing here is aspirational marketing — if something isn't fully wired, it says so.

The three services

The platform is a monorepo (Turborepo + pnpm) split into a control plane, a build worker, and an edge proxy — each deployed independently so they scale and fail independently.

ServiceRoleStackRuns on
Control planeDashboard, REST API, orchestrationNext.js 16, React 19, Prisma 7Vercel
Build workerClones, builds, uploads artifactNode 20, DockerAWS ECS Fargate (task per build)
Edge proxyServes deployed sitesExpress 5, Redis, S3AWS EC2 + Caddy

The control plane is the brain: it triggers builds, resolves domains for the proxy, handles auth and billing, and stores all state. The build worker and proxy are deliberately stateless — they get everything they need from the control plane and S3.

The deploy pipeline

What happens when you push a commit or click deploy:

  • The control plane creates a Deployment record and reserves a concurrent build slot (Redis Lua, atomic).
  • It launches one ephemeral ECS Fargate task with the repo URL, commit, build config, and decrypted env vars injected as the container's environment.
  • The worker clones the repo, runs install/build, and streams logs back to the control plane (which fans them out over Redis pub/sub to the proxy's SSE endpoint for the live log view).
  • The built artifact is uploaded to S3; the worker exits and the slot is released.
  • The control plane marks the deployment READY and pushes the domain→deployment mapping into Redis so the proxy can serve it with zero extra HTTP calls.
Four runtime targets are detected from the framework: STATIC (edge/CDN), NODEJS (AWS Lambda), PYTHON (Mangum-wrapped Lambda), and CONTAINER (a long-running Fargate service).

Multi-cloud provider abstraction

The interesting bit. Every cloud capability sits behind a TypeScript interface, selected per-org through a registry — so the orchestration code never names a specific cloud:

typescript
interface IComputeProvider {
  runBuild(spec: BuildSpec): Promise<BuildHandle>;
  describe(handle: BuildHandle): Promise<BuildStatus>;
}
// AWS ECS, GCP Cloud Run Jobs, Azure ACI, Kubernetes, and a raw Docker
// socket adapter all implement this — same contract, same env-var shape.
const compute = ProviderRegistry.compute(orgInfraConfig);

The same pattern covers storage (S3 / GCS / Azure Blob), serverless (Lambda / Cloud Run / Container Apps), secrets (Secrets Manager / Secret Manager / Key Vault / Vault), and logs. A migration engine can copy storage across providers and redeploy functions on a new target, with rollback.

Honest status

The AWS path is the one tested end-to-end with real deployments. GCP, Azure, and Kubernetes are complete reference implementations of the same interfaces but haven't been validated against live infrastructure — treat them as a demonstration of the abstraction, not a turnkey multi-cloud product.

Security & secrets

Envelope encryption for env vars

Environment variables and secrets are encrypted at rest with AES-256-GCM before they touch Postgres. Paid orgs get per-org AWS KMS envelope encryption: a per-org data key encrypts the values, and KMS encrypts the data key — so the database never holds anything decryptable on its own.

text
{ "_enc": "v2:<encryptedDEK_b64>:<ivHex>:<tagHex>:<ciphertextHex>" }

Service-to-service auth

The three services authenticate each other with shared-secret JWTs — the proxy signs requests to the control plane's reverse-proxy API, the build worker fetches its signing key from Secrets Manager at runtime (never as plaintext env), and browser log streaming is gated by a separate signed SSE token. Each secret pair must be byte-identical on both sides or it fails closed.

Data & runtime

  • Postgres (Supabase, via the transaction-mode pooler) through Prisma — the single source of truth for projects, deployments, domains, and billing.
  • Redis (Upstash) does a lot of quiet work: push-based domain cache (no HTTP call on a proxy cache hit), atomic concurrent-build-slot limiting, SSE log pub/sub, public-API rate limiting, and firewall-rule caching.
  • Edge proxy on EC2 with Caddy terminating TLS — wildcard certs via DNS-01 and on-demand TLS for arbitrary custom domains, gated by a verification callback before a cert is issued.

Tech stack

LayerChoice
FrameworkNext.js 16 (App Router), React 19, TypeScript 5
DataPrisma 7 + PostgreSQL, Redis (ioredis)
AuthBetter Auth (GitHub/Google OAuth, SAML SSO)
PaymentsStripe
UITailwind CSS v4, Radix UI, Recharts
Infra (build/host)AWS ECS Fargate, Lambda, S3, EC2, KMS, Secrets Manager

What this demonstrates

The point of the project is engineering range: a real distributed system with an orchestration control plane, ephemeral compute, an edge serving layer, a provider-abstraction layer with a migration engine, envelope encryption, and a full product surface (billing, RBAC, SSO, observability, a WAF, feature flags) on top. Browse the feature guides to see how each piece is used.

OverviewQuick Start