Documentation

Deployment Guide

What happens between "Deploy" and a live URL — the pipeline, the five ways to trigger it, how long it takes, build-time versus runtime variables, what a failure tells you, and how redeploys stay online.

What happens when you deploy

Every deploy — from the dashboard, a GitHub push, the API, the iOS app or an AI assistant — runs the same pipeline:

1

Fetch

For a GitHub deploy, the repository is cloned at the deploy branch (and root directory, if you set one) using your GitHub authorization; private repositories work the same as public ones. For a Docker deploy, the image reference is validated against the registry.

2

Detect

If the repository contains a Dockerfile it is used as-is. Otherwise the language and framework are detected — Node.js (including Next.js, Vite, Create React App and TanStack Start), Python (Django, Flask, FastAPI), Go, Java (Spring Boot, Maven/Gradle), PHP, Ruby and static sites — along with the runtime version from engines, .nvmrc or the lockfile, the listening port (Dockerfile EXPOSE, framework default, image inspection, then 3000) and the environment variables the code reads. AI-builder exports from Lovable, Bolt, v0 and Replit are recognised, including both Lovable stacks.

3

Check

Before the build starts SnapDeploy checks what would otherwise fail later: required environment variables are set, public build variables (VITE_*, NEXT_PUBLIC_*) do not contain anything that looks like a secret, the container size is one your plan allows, and the deploy limit has room. Failures here cost nothing — no build runs.

4

Build

A production Dockerfile is generated when you did not supply one, and the image is built on AWS CodeBuild with public build variables passed as build arguments. Build output streams live to the dashboard; the last lines are kept with the deployment record. Builds time out after 60 minutes.

5

Run

The image is pushed to a private registry and started as an isolated AWS Fargate task — one per container, with the memory and CPU of its size (512 MB, 2 GB or 4 GB). Runtime environment variables are injected at start.

6

Route

The load balancer waits until the task answers on its port, then routes your-app.containers.snapdeploy.app (and any custom domain, with free SSL) to it. On a redeploy the previous task keeps serving until the new one is healthy.

Five ways to deploy

How long it takes

Typical end-to-end times from trigger to healthy. About a minute of each is CodeBuild provisioning; dependency size and cold caches move the rest.

Application typeTypicalWhat dominates
Static site / Vite SPA1–3 minnpm install
Node.js / Next.js / TanStack Start2–4 mininstall + framework build
Python (Django, Flask, FastAPI)2–4 minpip install, compiled wheels
Go2–3 minmodule download
Java Spring Boot3–6 minMaven/Gradle dependency resolution
Pre-built Docker image1–2 minimage pull + health check

What triggers a deploy

  • Dashboard or app: the Deploy button on the container page.
  • GitHub push: every push to the linked branch, via the webhook installed when you linked the repository. The commit message and pusher appear in the history.
  • API: POST /api/mobile/deploy for a new app, or POST /api/mobile/github/link/{repoLinkId}/deploy to rebuild a linked one. Send Idempotency-Key: an identical request inside ten minutes returns the original deployment instead of starting another. See the API reference.
  • AI assistant: the MCP connector in Claude Code, Cursor, Windsurf, Codex CLI or Gemini CLI. Setup with a pre-filled token is on the API Keys page.

Deploy limit. The free tier allows 10 deploys a day (5 per rolling 12 hours) and 100 hours a month; every trigger counts, including builds that fail, and a unit is consumed when the build starts. Always-On containers have no deploy limit; a $1 Sprint Pack lifts it for 24 hours.

Build-time vs runtime variables

Build-time (public)

VITE_*, NEXT_PUBLIC_*, REACT_APP_* and similar are compiled into the front-end bundle. SnapDeploy passes them as build arguments, so they must be set before the build — the deploy wizard and the API scan the repository and ask for them. Changing one later means a redeploy. Anything public-prefixed that looks like a secret fails the build on purpose.

Runtime (private)

Database URLs, API keys and the like are injected when the task starts and never enter the image. Edit them on the container page; the change applies with a rolling restart. API tokens and AI assistants receive variable names only — values come back as (set).

Details and framework specifics: environment variables.

When a deployment fails

The deployment record keeps the error code, a plain-language message and the last lines of the build or container log, so the cause is on the page — not buried in a console. The most common codes:

CodeCauseFix
MISSING_ENTRY_POINTNode repo without index.js/server.js/app.js or a main/start scriptAdd one, set the root directory, or add a Dockerfile
DATABASE_DRIVER_MISMATCHThe app's database driver does not match the linked add-onInstall the right driver or link the matching add-on; the message names both
Missing required environment variablesVariables the code reads are not setSet them on the container page and deploy again
Health check never passedThe app did not answer on the detected port, or crashed at startRead the container log tail; check the port and start command
Build timed outMore than 60 minutesTrim dependencies, add a lockfile, or pre-build the image

On Always-On accounts, SmartFix AI reads pip and Dockerfile failures and proposes a commit you can apply from the dashboard. Every failed attempt still counts toward the free deploy limit, so read the log before retrying. More in troubleshooting.

Deployment history

Every container keeps its deployment history: status, commit, duration, the pipeline steps with timings, the error and log tail on failure, and who triggered it — you, a GitHub push (with the pusher's login) or an AI assistant, shown as "via Claude Code", "via Cursor" and so on. The same records are available at GET /api/mobile/containers/{id}/deployments and through the connector's get_deployments tool, which is how an assistant diagnoses a failed build.

Redeploys without downtime

  • The new task starts alongside the old one
  • The load balancer waits for the new task's health check
  • Traffic moves to the new task, then the old one stops
  • If the new task never becomes healthy, the old one keeps serving and the deployment is marked failed
  • A sleeping free-tier container is woken by the deploy; WebSocket apps need Always-On so connections are never dropped by sleep

Frequently asked questions

How long does a deployment take?

Typically two to six minutes from trigger to healthy, most of it in the AWS CodeBuild build stage (about a minute of that is CodeBuild provisioning). Pre-built Docker images skip the build and are usually live in one to two minutes. Builds time out after 60 minutes.

Do I need a Dockerfile?

No. If the repository has one it is used as-is; otherwise SnapDeploy detects the language and framework (Node.js incl. Next.js, Vite and TanStack Start, Python Django/Flask/FastAPI, Go, Java Spring Boot, PHP, Ruby, static sites) and generates a production Dockerfile for it.

What counts as a deploy against the free limit?

Every triggered build: manual deploys, GitHub pushes, API and assistant triggers — including ones that fail. The free tier allows 10 deploys a day (5 per rolling 12 hours) and 100 hours a month. Identical API requests inside ten minutes with the same Idempotency-Key are deduplicated and consume only one.

Why did my build fail with MISSING_ENTRY_POINT?

A Node.js repository has no index.js, server.js or app.js in the configured root directory and no main or start script in package.json, so the generated Dockerfile has nothing to run. Add one, set the correct root directory, or add your own Dockerfile.

Can I change environment variables after the first deploy?

Yes. Runtime variables are applied with a rolling restart from the container page. Public build-time variables such as VITE_* and NEXT_PUBLIC_* are compiled into the bundle, so changing them requires a redeploy — the container page says which is which.

Does a redeploy cause downtime?

Not on a running container. The new task starts beside the old one, the load balancer waits until it passes its health check, then traffic moves and the old task stops. If the new build never becomes healthy the old one keeps serving and the deployment is marked failed. A sleeping free-tier container is woken by the deploy.

Can I deploy from CI or from an AI assistant?

Yes. POST /api/mobile/deploy with a scoped token creates, links and builds in one request (send an Idempotency-Key so re-runs are safe), and the official MCP connector lets Claude Code, Cursor, Codex CLI and Gemini CLI deploy from chat. Deployment history shows who triggered each build.

Can I roll back to a previous deployment?

One-click rollback is in progress on the roadmap. Today, revert the commit in Git and push, or trigger a deploy of the earlier commit's branch; every deployment's image is kept and the history shows exactly which commit each build used.

Related reading