Railway Cloud Deployment
Relevant source files
The following files were used as context for generating this wiki page:
The Syllogic personal finance platform supports a high-availability cloud deployment via Railway. This deployment path utilizes a multi-service architecture designed to handle web traffic, background processing, and persistent data storage with automated lifecycle management.
Railway deployment is primarily orchestrated through a specialized Docker Compose configuration that leverages Railway's Shared Variables and internal networking to link seven distinct services into a cohesive environment.
Sources: deploy/railway/README.md:3-8, README.md:104-106
Infrastructure Architecture
The deployment consists of seven interconnected services. Unlike a local Docker environment, Railway provides the reverse proxy and TLS termination automatically, removing the need for a dedicated Caddy or Nginx service.
Service Grid
The following diagram illustrates the relationship between the deployed services on Railway:
The Railway proxy handles incoming traffic for the app service, while internal services communicate over Railway's private networking.
Sources: deploy/railway/docker-compose.yml:25-103, deploy/railway/README.md:130-134
Service Configuration
Railway uses internal DNS (e.g., SERVICE_NAME.railway.internal:PORT) for service-to-service communication. The deployment utilizes specific start commands and environment variables to wire these services together.
Component Details
| Service | Image/Source | Primary Command | Purpose |
|---|---|---|---|
| app | personal-finance-frontend | node scripts/migrate.js && next start | Next.js Frontend & Auth |
| backend | personal-finance-backend | Default (Gunicorn) | FastAPI Business Logic |
| worker | personal-finance-backend | celery -A celery_app worker | Background Job Processing |
| beat | personal-finance-backend | celery -A celery_app beat | Scheduled Tasks |
| mcp | personal-finance-backend | uvicorn mcp_server:app | Programmatic Access Server |
| postgres | postgres:16-alpine | Default | Persistent SQL Database |
| redis | redis:7-alpine | redis-server --appendonly yes | Cache & Message Broker |
Sources: deploy/railway/docker-compose.yml:30-103, deploy/railway/README.md:46-52
Data Persistence and Migrations
Volume Management
Railway maintains three persistent volumes to ensure data survives service redeployments:
- postgres_data: Mounted at
/var/lib/postgresql/datafor the database. - redis_data: Mounted at
/datafor the Redis cache. - uploads_data: Mounted at
/app/public/uploadsfor profile photos, company logos, and CSV imports.
Sources: deploy/railway/docker-compose.yml:105-108, deploy/railway/README.md:88-92
Automated Migrations
To ensure the PostgreSQL schema (managed by Drizzle ORM) is up to date, the app service executes a migration script before booting the Next.js server. This is critical for the initialization of BetterAuth tables (users, sessions, auth_accounts).
// From frontend/scripts/migrate.js
async function main() {
const databaseUrl = process.env.DATABASE_URL;
// ... checks migrations folder ...
const db = drizzle(sql);
await migrate(db, { migrationsFolder });
}
The startup command in Railway is configured as:
node scripts/migrate.js && exec node_modules/.bin/next start -p 3000 -H 0.0.0.0
Sources: frontend/scripts/migrate.js:100-140, deploy/railway/README.md:58-64, frontend/railway.toml:13
Environment Configuration
Deployment requires a set of Shared Variables in the Railway UI. These variables are referenced by all services using the ${{shared.VAR}} syntax.
| Variable | Requirement | Description |
|---|---|---|
POSTGRES_PASSWORD | Required | Secure password for the database user |
BETTER_AUTH_SECRET | Required | Key for signing authentication sessions |
INTERNAL_AUTH_SECRET | Required | Shared secret for backend-to-frontend signed requests |
OPENAI_API_KEY | Optional | Enables AI categorization features |
LOGO_DEV_API_KEY | Optional | Enables company logo enrichment |
Note: Railway service references automatically derive DATABASE_URL, REDIS_URL, APP_URL, and BACKEND_URL. Manual configuration of these variables is discouraged to avoid overriding the dynamic service-to-service wiring.
Sources: deploy/railway/README.md:20-30, deploy/railway/docker-compose.yml:52-53
Deployment Lifecycle
The deployment flow differs between a Compose Import and a Source Deploy:
Health and Security
Networking Restrictions
By default, only the app service (and optionally mcp) should have Public Networking enabled. All other services (Postgres, Redis, Backend, Worker, Beat) should remain private to ensure they are only accessible within the Railway project environment.
Healthchecks
The app service healthcheck performs a two-step verification:
- File System: Checks that the
/app/public/uploadsdirectory is writable (verifying volume health). - HTTP: Checks the local Next.js endpoint for a 200 OK response.
Sources: deploy/railway/README.md:41-44, deploy/railway/docker-compose.yml:93-98
Summary
Railway Cloud Deployment provides a production-ready environment for Syllogic by automating container orchestration, SSL/TLS termination, and database migrations. By using persistent volumes for uploads and a shared variable model for secrets, the system maintains high data integrity and security while scaling internal processing via dedicated Celery workers and beats.