Two Dockerfiles in your Wasp project, two containers from the same GitHub repository, a managed PostgreSQL next to them. SnapDeploy installs the Wasp CLI and runs wasp build on its own builders, so you push source, not build output, and every push redeploys.
Free tier: 4 containers, 512 MB each, 100 hours a month, 10 deploys a day. No credit card. Always-On from $12 a month, PostgreSQL from $1 for 12 hours or $29 a month.
Last verified 6 October 2026 with Wasp 0.25 and Node.js 24: the sample repository below was built and run with these exact files. Every number is from the free-tier docs and the add-on pricing page.
Wasp's own documentation has guides for the providers below. What each one gives a server, a client and a database, from the providers' own pages on 6 October 2026.
| Host | How the server gets there | Client | PostgreSQL | Free to start |
|---|---|---|---|---|
| SnapDeploy | Push the repo; a Dockerfile installs Wasp and builds on the platform's ARM64 builders | Second container from the same repo (nginx) | Managed add-on: $1 for 12 hours, Mini $29 a month | 4 containers, 100 hours a month, no card; sleeps after 15 minutes |
| Render | Blueprint builds from source on Render | Static site service | Free Postgres, deleted after 30 days; paid from there | 750 instance-hours, 0.1 CPU, sleeps after 15 minutes; 10 to 15 minute builds on the free tier per Wasp's guide |
| Railway | Railway CLI deploys the built output | Separate service | Railway Postgres | One-time $5 trial credit, then $5 a month |
| Fly.io | fly launch from .wasp/out with the generated Dockerfile | Elsewhere (the guide suggests Netlify) | Fly Postgres | No free allowance for new organisations; pay as you go |
Isolation: every SnapDeploy container, free tier included, runs as its own AWS Fargate task with a reserved 0.25 vCPU and 512 MB. AWS runs each Fargate task on a single-use, single-tenant compute instance, so your Wasp server never shares a host with another customer's app. Render's free instance is 0.1 CPU and 512 MB, Railway's trial runs on shared vCPU cores (its own wording), and Fly.io gives each Machine its own VM but has no free tier.
Sources: wasp.sh/docs (deployment guides for Render, Railway and Fly.io, read 6 October 2026); render.com/docs/free and render.com/docs/compute-plans; railway.com/pricing and docs.railway.com/pricing/free-trial; fly.io/docs/about/pricing and docs.fly.io/machines; aws.amazon.com/fargate/faqs (task isolation). SnapDeploy figures from /docs/free-tier and /addon-pricing.
Wasp needs PostgreSQL in production and will not build with SQLite, so switch the Prisma datasource first, run wasp db migrate-dev once locally and commit the migrations/ folder. Then add the three files below to the project root.
Dockerfile for the serverIt mirrors the Dockerfile Wasp generates in .wasp/out, with one extra stage: the Wasp CLI is installed and wasp install && wasp build run inside the image, so the repository stays source-only. Debian images rather than Alpine, because the Wasp CLI ships glibc binaries for linux/arm64 and linux/x64.
ARG WASP_VERSION=0.25.0
ARG NODE_IMAGE=node:24-bookworm-slim
FROM ${NODE_IMAGE} AS base
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
FROM base AS builder
ARG WASP_VERSION
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 build-essential \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g @wasp.sh/wasp-cli@${WASP_VERSION}
WORKDIR /app
COPY . .
RUN wasp install && wasp build
RUN cd .wasp/out/server \
&& npm install \
&& npx prisma generate --schema=../db/schema.prisma \
&& npm run bundle \
&& mkdir -p node_modules
FROM base AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/.wasp/out/sdk ./.wasp/out/sdk
COPY --from=builder /app/.wasp/out/server/node_modules ./.wasp/out/server/node_modules
COPY --from=builder /app/.wasp/out/server/bundle ./.wasp/out/server/bundle
COPY --from=builder /app/.wasp/out/server/package*.json ./.wasp/out/server/
COPY --from=builder /app/.wasp/out/db ./.wasp/out/db
WORKDIR /app/.wasp/out/server
EXPOSE 3001
ENTRYPOINT ["npm", "run", "start-production"]
Add a .dockerignore with node_modules, .wasp, .git and .env.* so the build context is the source only. start-production runs prisma migrate deploy and then the server, exactly as Wasp's generated image does.
Services → Add database → PostgreSQL. The $1 DB Sprint Pack gives a full Mini-tier database for 12 hours with a 24-hour window to keep it; the Mini tier is $29 a month. Once the add-on is linked to the server container, DATABASE_URL is injected into its environment; you can also paste the connection string from the add-on's credentials page as a variable yourself.
Deploy Your Application → GitHub → the repository and branch. The Dockerfile is detected; port 3001 comes from its EXPOSE line and SnapDeploy injects PORT=3001, which the Wasp server reads. Set these variables before the first build:
| Variable | Value |
|---|---|
DATABASE_URL | injected by the linked add-on, or pasted from its credentials |
JWT_SECRET | a random string of at least 32 characters |
WASP_SERVER_URL | https://<server-name>.containers.snapdeploy.app (the container name you choose) |
WASP_WEB_CLIENT_URL | the client URL from step 5; any placeholder for the first build |
The build installs Wasp, compiles the app and bundles the server; expect a few minutes the first time. When the image is pushed the container starts, applies the migrations and answers at its URL. The health check accepts the server's root path, so no extra route is needed. If your app uses an OAuth provider or an email sender, add those variables here too.
The client is static files built by Vite. A second Dockerfile in the same repository builds them and serves them with nginx, with the single-page-app fallback that client-side routes like /login need.
client.Dockerfile and nginx.confARG WASP_VERSION=0.25.0
ARG NODE_IMAGE=node:24-bookworm-slim
FROM ${NODE_IMAGE} AS builder
ARG WASP_VERSION
ARG REACT_APP_API_URL
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl ca-certificates python3 build-essential \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g @wasp.sh/wasp-cli@${WASP_VERSION}
WORKDIR /app
COPY . .
RUN wasp install && wasp build
RUN test -n "$REACT_APP_API_URL" || (echo "REACT_APP_API_URL is not set" && exit 1)
RUN REACT_APP_API_URL=${REACT_APP_API_URL} npx vite build
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/.wasp/out/web-app/build /usr/share/nginx/html
EXPOSE 80
Wasp's Vite build emits 200.html as the entry page, not index.html, and COPY merges into the nginx image's html directory, so the stock welcome page is removed first and nginx is told to serve 200.html:
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index 200.html;
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location / {
try_files $uri $uri/ /200.html;
}
}
Deploy Your Application → GitHub → the same repository → Advanced Options → Dockerfile Path client.Dockerfile. Add one variable before the first build:
| Variable | Value |
|---|---|
REACT_APP_API_URL | the server URL from step 3 |
Vite bakes REACT_APP_API_URL into the compiled JavaScript. SnapDeploy passes REACT_APP_, VITE_ and NEXT_PUBLIC_ variables into the Docker build as build arguments, which is why the Dockerfile declares it as ARG and refuses to build without it. If you change it later, redeploy; a restart is not enough.
On the server container set WASP_WEB_CLIENT_URL to the client's URL and redeploy. Open the client URL, sign up, create something. From now on every push to the branch rebuilds both containers; new Prisma migrations committed with your code are applied by the server on its next start.
The two containers follow the same rules as any other; the complete list is on the free-tier page.
No. The server Dockerfile on this page installs the Wasp CLI and runs wasp install and wasp build inside the build, so the repository holds your app's source and every push to the branch rebuilds the container. You never commit the .wasp/out output.
A built Wasp app is a Node.js API server plus a static React client, and Wasp's own docs deploy them as two things with two URLs. On SnapDeploy they are two containers from the same repository: the server from Dockerfile and the client from client.Dockerfile, chosen with the Dockerfile Path field under Advanced Options. Both fit in the free tier's 4 containers.
From a managed PostgreSQL add-on next to the containers: the $1 DB Sprint Pack runs for 12 hours to try things, the Mini tier is $29 a month. Link it to the server container and DATABASE_URL is injected into the environment; the server runs prisma migrate deploy on every start, so committed migrations are applied automatically.
Through REACT_APP_API_URL, which Vite bakes into the JavaScript at build time. Add it as an environment variable on the client container before the first build: SnapDeploy passes REACT_APP_, VITE_ and NEXT_PUBLIC_ variables into the Docker build as build arguments. Changing it later needs a redeploy, not a restart.
No. The platform probes the common health paths and then the root path before routing traffic, and the Wasp 0.25 server answers GET / with 200, so the deploy passes without any change to the app.
Yes, as a demo: two of the four free containers, 100 container-hours a month shared, no credit card. Both containers sleep after 15 idle minutes. A browser visit wakes the client, but the client's API calls do not wake a sleeping server, so for anything people depend on run the server on Always-On at $12 a month; the client can stay free.
Wasp 0.25, the current release on 6 October 2026, with Node.js 24 in the build. The Wasp version is an argument at the top of each Dockerfile; bump it when you upgrade the app.
Two Dockerfiles, a PostgreSQL add-on, no credit card for the containers. Always-On from $12 a month when the server has to stay up.
Deploy Free TodayThe first managed container PaaS to offer a one-time 24-hour Always-On pass under $5. Unlimited deploys + Always-On for one Small (512 MB) container — including WebSockets & real-time apps. No subscription, no auto-renewal. Stack two for 48 hours.
Need a managed database too? DB Sprint Pack — $1 / 12h for Postgres, MySQL, MariaDB, Mongo, Redis, or RabbitMQ.