Skip to content

Git Push Deploy

Stackpad deploys your application automatically every time you push to your configured branch. This guide explains how the pipeline works, how to set it up, and what to do when things go wrong.

Connecting GitHub

Before you can deploy, you need to connect your GitHub account to Stackpad.

GitHub OAuth

When you click Connect GitHub (in organization settings or during project creation), Stackpad requests access to your GitHub account via OAuth. This grants Stackpad permission to:

  • List your repositories (public and private you have access to)
  • Read repository contents (to clone and build)
  • Create webhooks (to receive push events)

Your GitHub access token is stored securely and used to clone private repositories during builds.

Webhook setup

When you create a web service from GitHub, Stackpad automatically installs a webhook on the repository. This webhook:

  • Listens for push events (to trigger deploys) and delete events (to clean up preview branches)
  • Uses HMAC-SHA256 signature verification to prevent spoofing
  • Is visible in your repository’s GitHub settings under Webhooks

The webhook is automatically removed when you delete the service from Stackpad.

How deployment works

When you push to your deployment branch (e.g. main), here’s what happens step by step:

  1. GitHub sends a webhook to Stackpad’s API
  2. Stackpad matches the push to the correct service by repository URL and branch
  3. The deployment is queued (max 4 concurrent builds per build node)
  4. Stackpad clones your repository on a dedicated build node
  5. Your framework is detected from package.json and config files
  6. A Dockerfile is generated optimized for your framework
  7. The Docker image is built using BuildKit (10-minute timeout)
  8. The image is pushed to Stackpad’s private registry
  9. The compute node pulls the image
  10. A new container starts alongside the old one
  11. Stackpad runs a health check (90-second timeout)
  12. If healthy, Caddy switches traffic to the new container
  13. The old container stops after traffic drains

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

Build configuration

For most projects, Stackpad’s automatic detection handles everything. Here’s what you can customize:

Build command

Auto-detected from your package.json build script. Override it in service settings if needed.

Root directory

For monorepos, specify the directory of your app (e.g. apps/web). Stackpad detects pnpm workspaces and installs dependencies from the workspace root, then builds from the specified directory.

Package manager

Automatically detected from the lockfile:

LockfilePackage managerInstall command
pnpm-lock.yamlpnpmpnpm install --frozen-lockfile
yarn.lockyarnyarn install --frozen-lockfile
package-lock.jsonnpmnpm ci

Build environment

Builds run on dedicated build nodes:

ResourceValue
CPU4 vCPU
RAM16 GB
Max concurrent builds4 per build node
Build timeout10 minutes

Build-time environment variables are injected as Docker build args. This means NEXT_PUBLIC_* variables for Next.js are available during the build.

Viewing build logs

Every deployment has build logs that show the full output of the build process:

  1. Go to the Deployments tab (on the project or service page)
  2. Click any deployment
  3. The Build Logs panel shows the complete output

Build logs are essential for debugging failed deployments. They show:

  • Dependency installation output
  • Build command output (TypeScript errors, bundler warnings)
  • Docker image creation
  • Any errors that caused the build to fail

The log viewer auto-scrolls to follow new output and shows a connection indicator (green = streaming live).

Deployment status

StatusDescriptionDuration
QueuedWaiting for a build slotDepends on queue
BuildingCloning, installing, buildingUp to 10 min
DeployingStarting container, health checkUp to 90 sec
ReadyLive and serving traffic
FailedBuild or health check failed
StoppedManually stopped

Manual deployments

Trigger a deployment manually from the dashboard without pushing code:

  1. Go to your service detail page
  2. Click Redeploy

This is useful for:

  • Applying environment variable changes (they don’t auto-trigger deploys)
  • Retrying a failed deployment
  • Picking up a newly added database’s DATABASE_URL

Common build issues

ProblemCauseSolution
Build timeout (10 min)Large monorepo, slow installsOptimize dependencies, check lockfile
TypeScript errorsCode doesn’t compileFix errors locally first, push again
Missing dependenciesNot in package.jsonAdd dependency and push
NEXT_PUBLIC_* not workingVariable not setAdd to project environment variables
Monorepo build failureWrong root directoryCheck root directory in service settings
Health check failureApp doesn’t start in 90sSee Rollbacks guide

What’s next?