Railway Deployment - Internal Services
Complete guide for deploying GoGrab internal infrastructure to Railway
🚂 Railway Deployment - Internal Services
Our backend APIs and frontend app are deployed to Railway via GitHub deploy branches
To deploy the user platform (Cloudflare), see User Platform Deployment.
To deploy the internal services, see the following sections.
Overview
Backend (Railway) services hosts our internal infrastructure - the services that power the GoGrab platform:
| Service | Purpose | Domain | Port |
|---|---|---|---|
backend-api |
Core API, auth, spaces | api.gograb.space |
3000 |
backend-ai-api |
AI generation, MCP | ai-api.gograb.space |
3001 |
backend-docs-api |
Documentation API | docs-api.gograb.space |
3002 |
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Railway Deployment Flow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ GitHub (editor2) │
│ ├── main branch (development) │
│ │ │ │
│ │ │ merge │
│ │ ▼ │
│ ├── deploy/api ─────────► Railway Service: backend-api │
│ │ └── api.gograb.space │
│ │ │
│ ├── deploy/ai-api ──────► Railway Service: backend-ai-api │
│ │ └── ai-api.gograb.space │
│ │ │
│ ├── deploy/docs-api ────► Railway Service: backend-docs-api │
│ │
└─────────────────────────────────────────────────────────────────┘
Deploy Branch Strategy
Each service has a dedicated deploy branch containing a railway.toml at the root:
Branch → Service Mapping
| Branch | Service | Dockerfile |
|---|---|---|
deploy/api |
backend-api | deployment/Dockerfile.railway.backend |
deploy/ai-api |
backend-ai-api | deployment/Dockerfile.railway.backend-ai |
deploy/docs-api |
backend-docs-api | deployment/Dockerfile.railway.docs-api |
Why Deploy Branches?
- Isolation: Each service deploys independently
- Control: Merge only when ready to deploy
- Rollback: Easy to revert specific services
- Monorepo Support: Railway watches specific branches, not paths
Deployment Commands
Deploy Single Service
# Backend API
git checkout deploy/api
git merge main --no-edit
git push origin deploy/api
git checkout main
# Backend AI API
git checkout deploy/ai-api
git merge main --no-edit
git push origin deploy/ai-api
git checkout main
# Backend Docs API
git checkout deploy/docs-api
git merge main --no-edit
git push origin deploy/docs-api
git checkout main
Deploy All Services
# Using yarn script
yarn railway:deploy:all
# Or manually
for branch in deploy/api deploy/ai-api deploy/docs-api; do
git checkout $branch
git merge main --no-edit
git push origin $branch
done
git checkout main
NPM Scripts Available
yarn railway:deploy:backend # Deploy backend-api
yarn railway:deploy:ai # Deploy backend-ai-api
yarn railway:deploy:docs # Deploy backend-docs-api
yarn railway:deploy:all # Deploy all services
Railway Configuration
railway.toml (per deploy branch)
Each deploy branch has a railway.toml at the repo root:
# deploy/api branch - railway.toml
[build]
builder = "DOCKERFILE"
dockerfilePath = "deployment/Dockerfile.railway.backend"
dockerContext = "."
[deploy]
startCommand = "node dist/apis/backend-api/main.js"
healthcheckPath = "/api/health"
healthcheckTimeout = 300
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10
Environment Variables (Railway Dashboard)
| Variable | Required | Description |
|---|---|---|
NODE_ENV |
Yes | production |
JWT_SECRET |
Yes | JWT signing key |
MONGODB_CONNECTION_STRING |
Yes | MongoDB Atlas URI |
ALLOWED_ORIGINS |
Yes | CORS origins |
PORT |
Auto | Set by Railway |
Service-Specific Variables
| Service | Variable | Description |
|---|---|---|
| backend-ai-api | ANTHROPIC_API_KEY |
Claude API key |
| backend-ai-api | OPENAI_API_KEY |
OpenAI API key |
| backend-ai-api | GITLAB_API_TOKEN |
GitLab access |
| backend-ai-api | CLOUDFLARE_API_TOKEN |
Cloudflare access |
Dockerfiles
Located in deployment/ folder:
Backend API
# deployment/Dockerfile.railway.backend
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn nx build backend-api --configuration=production
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist/apis/backend-api ./
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "main.js"]
Backend AI API
# deployment/Dockerfile.railway.backend-ai
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN yarn nx build backend-ai-api --configuration=production
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist/apis/backend-ai-api ./
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3001
CMD ["node", "main.js"]
Health Checks
Endpoints
# Backend API
curl https://api.gograb.space/api/health
# Backend AI API
curl https://ai-api.gograb.space/ai-api/health
# Backend Docs API
curl https://docs-api.gograb.space/docs-api/health
Expected Response
{
"status": "ok",
"timestamp": "2026-01-24T12:00:00.000Z",
"service": "backend-api",
"version": "1.0.0"
}
Troubleshooting
Build Uses Railpack Instead of Dockerfile
Symptom: Error "No start command was found"
Fix: Ensure railway.toml exists at repo root in deploy branch with:
[build]
builder = "DOCKERFILE"
Multiple Services Found
Symptom: "Please specify a service via --service flag"
Fix: When using CLI, specify service:
railway up -d --service backend-api
502 Bad Gateway After Deploy
Symptom: Service returns 502 errors
Fixes:
- Check health endpoint is responding
- Verify
PORTenvironment variable is used - Check Railway logs for startup errors
- Ensure
startCommandin railway.toml is correct
CORS Errors
Symptom: Browser shows CORS errors
Fix: Add origin to ALLOWED_ORIGINS in Railway dashboard:
https://gograb.space,https://app.gograb.space,http://localhost:5200
Troubleshooting
Railway Deployment Not Triggering (Session 84 Fix)
Symptom: You push to deploy/api, deploy/ai-api, or deploy/docs-api but Railway doesn't start a build. No deployment appears, or it shows "No changes to watched files" and skips.
Root Cause: Railway service is not configured to watch the correct deploy branch, OR the Watch Paths filter is excluding your changes.
Solutions (in order of preference):
1. Force Redeploy via CLI (Immediate Fix)
# Link to the correct project and service
railway link -p <PROJECT_ID> -s <SERVICE_NAME>
# Force a rebuild of the last deployment
railway redeploy --yes
Project IDs:
backend-api:3990549d-4313-47e4-9682-d17b382bdba2backend-ai-api:3990549d-4313-47e4-9682-d17b382bdba2docs-api:3990549d-4313-47e4-9682-d17b382bdba2
2. Use --force Flag (Creates Trigger File)
yarn deploy --apis api --force
This creates a .railway-trigger file in the watched app directory (e.g., apis/backend-api/).
Note: This only works if Railway IS watching the deploy branch but filtering files.
3. Fix Railway Branch Configuration (Permanent Fix)
If Railway isn't watching the deploy branch at all:
- Go to Railway Dashboard → Service → Settings → Source
- Change the branch from
maintodeploy/api(or the appropriate deploy branch) - Ensure Watch Paths includes the app directory:
apis/backend-api/**
4. Understanding Watch Paths
Railway's Watch Paths (Settings → Build) determine which file changes trigger a build:
apis/backend-api/**- Only changes in this directory trigger buildslibs/libs-api/**- Shared librariespackage.json,yarn.lock- Dependency changes
Important: Watch Paths only filter WITHIN the watched branch. If Railway isn't watching deploy/api at all, no amount of file changes will trigger a build.
Project IDs (Reference)
| Project | Railway Project ID |
|---|---|
| GoGrab API | 3990549d-4313-47e4-9682-d17b382bdba2 |
| GoGrab AI API | 3990549d-4313-47e4-9682-d17b382bdba2 |
| GoGrab Docs API | 3990549d-4313-47e4-9682-d17b382bdba2 |
Related Files
| File | Purpose |
|---|---|
deployment/Dockerfile.railway.backend |
Backend API container |
deployment/Dockerfile.railway.backend-ai |
AI API container |
deployment/Dockerfile.railway.docs-api |
Docs API container |
deployment/Dockerfile.railway.simple |
Frontend container |
deployment/railway-simple-server.js |
Frontend static server |
See Also: