Railway and Vercel together give you a production-grade deployment with managed infrastructure, automatic TLS, and preview environments — without configuring servers. Railway hosts your FastAPI backend and PostgreSQL database, and Vercel hosts your Next.js frontend. This guide walks you through both deployments and explains how to wire them together.Documentation Index
Fetch the complete documentation index at: https://docs.shipfastai.dev/llms.txt
Use this file to discover all available pages before exploring further.
Railway’s free Hobby plan is suitable for experimenting, but it imposes usage limits and may sleep inactive services. For a real production workload, upgrade to Railway’s Pro plan ($20/month) to get always-on services, more compute, and priority support.
Deploy the backend to Railway
Create a Railway project and add a PostgreSQL database
Log in to railway.app and create a new project. Inside the project, click New → Database → Add PostgreSQL. Railway provisions a managed PostgreSQL instance and automatically injects a
DATABASE_URL variable into services in the same project.Connect your GitHub repo and select the backend directory
Click New → GitHub Repo, authorize Railway to access your repository, and select it. In the service settings, set the Root Directory to the backend path for your tier:
- Basic:
products/basic/backend - Pro:
products/pro/backend - Enterprise:
products/enterprise/backend
Dockerfile in that directory and uses it for builds.Set required environment variables
In the service’s Variables tab, add the following.
DATABASE_URL is already injected by the linked PostgreSQL service — do not override it.| Variable | Description |
|---|---|
JWT_SECRET | A long, random string used to sign JWT tokens |
STRIPE_SECRET_KEY | Your Stripe secret key (sk_live_...) |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret (whsec_...) |
STRIPE_PRICE_ID_MONTHLY | Stripe price ID for the monthly plan |
STRIPE_PRICE_ID_YEARLY | Stripe price ID for the yearly plan |
RESEND_API_KEY | Resend API key for transactional email |
FROM_EMAIL | Sender address for outgoing email |
FRONTEND_URL | Your Vercel frontend URL (set after frontend is deployed) |
CORS_ORIGINS | Same as FRONTEND_URL |
APP_ENV | Set to production |
DEBUG | Set to false |
Configure the start command
In the service settings under Deploy, set the Start Command to:Railway injects the
$PORT variable automatically. Do not hardcode a port number.Deploy the frontend to Vercel
Connect your GitHub repo to Vercel
Log in to vercel.com, click Add New Project, and import your GitHub repository. Vercel detects the monorepo structure automatically.
Set the root directory
In the project configuration, expand Root Directory and set it to the frontend path for your tier:
- Basic:
products/basic/frontend - Pro:
products/pro/frontend - Enterprise:
products/enterprise/frontend
Set environment variables
Before deploying, add the following environment variables in the Vercel dashboard under Settings → Environment Variables:
Variables prefixed with
| Variable | Value |
|---|---|
NEXT_PUBLIC_API_URL | Your Railway backend URL from the previous section |
NEXT_PUBLIC_STRIPE_PRICE_ID_MONTHLY | Stripe monthly price ID |
NEXT_PUBLIC_STRIPE_PRICE_ID_YEARLY | Stripe yearly price ID |
NEXT_PUBLIC_ are embedded into the browser bundle at build time, so you must redeploy after changing them.Custom domain setup
You can add a custom domain in both services from their respective dashboards.- Railway: Go to your service → Settings → Networking → Custom Domain. Add your domain and update your DNS records as instructed.
- Vercel: Go to your project → Settings → Domains. Add your domain and follow the DNS verification steps.
FRONTEND_URL and CORS_ORIGINS variables on Railway, and redeploy the backend. After pointing your custom domain to the frontend, update NEXT_PUBLIC_API_URL on Vercel and redeploy the frontend.
Environment variable checklist
Use this table to confirm every variable is configured in the right service before going live.| Variable | Set on Railway | Set on Vercel |
|---|---|---|
DATABASE_URL | Auto-injected | — |
JWT_SECRET | Yes | — |
STRIPE_SECRET_KEY | Yes | — |
STRIPE_WEBHOOK_SECRET | Yes | — |
STRIPE_PRICE_ID_MONTHLY | Yes | — |
STRIPE_PRICE_ID_YEARLY | Yes | — |
RESEND_API_KEY | Yes | — |
FROM_EMAIL | Yes | — |
FRONTEND_URL | Yes | — |
CORS_ORIGINS | Yes | — |
APP_ENV | Yes | — |
NEXT_PUBLIC_API_URL | — | Yes |
NEXT_PUBLIC_STRIPE_PRICE_ID_MONTHLY | — | Yes |
NEXT_PUBLIC_STRIPE_PRICE_ID_YEARLY | — | Yes |