Tutorials

How to Sync AI Rules on Railway

Ensuring AI rules are validated in Railway deployments. Dockerfile integration, Nixpacks build hooks, and the workflow for backend services deployed on Railway.

5 min readยทJuly 5, 2025

Railway deploys backends. AI rules encode: health checks, graceful shutdown, env vars, and structured logging โ€” the patterns Railway needs.

Nixpacks prebuild, Dockerfile validation, health checks, SIGTERM handling, and internal service communication

AI Rules for Railway-Deployed Services

Railway deploys applications from git repositories, supporting: Nixpacks (auto-detected build system), Dockerfiles (custom build process), and pre-built images. Railway is popular for backend services (Node.js APIs, Python services, Go microservices) and databases. AI rules for Railway projects: focus on backend conventions (API patterns, database interactions, error handling) rather than frontend concerns (no HTML rendering, no CSS).

Railway's build process: Nixpacks auto-detects the language and framework, generating a build plan. For Node.js: it runs npm install and npm run build. For Python: it runs pip install and any build commands. The AI rules validation: hooks into this build process. Railway also supports a railway.toml configuration file for custom build and deploy settings.

The validation approach: same prebuild script used for Vercel and Netlify. Add 'prebuild': 'node scripts/validate-rules.js' to package.json. Railway runs prebuild before the build command. The script checks CLAUDE.md existence and version. For Dockerfile-based deployments: add the validation as a build step in the Dockerfile.

Step 1: Nixpacks Build Validation

For Nixpacks-based Railway deployments (the default): the prebuild script in package.json runs automatically. Railway's Nixpacks: detects Node.js from package.json, runs npm install, runs prebuild (if defined), then runs the build command. The validation: happens before the build, exactly like Vercel and Netlify.

For Python projects: add a validation script in the build process. In railway.toml: [build] buildCommand = 'python scripts/validate_rules.py && python -m build'. The validation script: checks for CLAUDE.md (or CONVENTIONS.md for Python projects), validates the version, and exits with a non-zero code if validation fails. Railway: stops the deployment if the build command fails.

For Go projects: add validation to the Makefile or build script. In railway.toml: [build] buildCommand = 'go run scripts/validate-rules.go && go build -o app ./cmd/server'. The pattern: validate rules โ†’ then build the application. If validation fails: the build stops, the deployment does not proceed. AI rule: 'The validation pattern is language-agnostic: validate rules as the first step of the build command. The implementation language matches the project language.'

๐Ÿ’ก The Prebuild Script Works on Railway Without Changes

The same prebuild script from Vercel and Netlify: works on Railway without modification. Railway's Nixpacks: detects Node.js, runs npm install, runs prebuild, then runs build. The validation script: portable across all three platforms. Write once, validate everywhere. If you deploy the same project to Vercel (frontend) and Railway (backend): both run the same prebuild validation.

Step 2: Dockerfile Validation

For Dockerfile-based Railway deployments: add the validation as a build stage. In the Dockerfile: COPY CLAUDE.md . (copy the rules file into the build context), RUN node scripts/validate-rules.js (run validation during build โ€” fails the build if rules are missing or outdated), then proceed with the normal build steps. The validation: runs during docker build, before the application is compiled.

Multi-stage Dockerfile pattern: Stage 1 (validate): copy the rules file and run validation. Stage 2 (build): copy source code and build the application. Stage 3 (production): copy the built application for deployment. The validation stage: adds ~1 second to the build. If it fails: the build stops at stage 1, saving the time of stages 2 and 3. AI rule: 'Validation in the first Docker stage: fails fast. No time wasted building an application that will be deployed without current rules.'

Railway-specific Dockerfile tip: Railway sets the PORT environment variable. The Dockerfile should use: EXPOSE $PORT and the application should listen on process.env.PORT. The rules validation: does not interact with PORT. But the rules file should include: 'Railway deployment: the application listens on process.env.PORT (not a hardcoded port). Railway assigns the port dynamically.' This rule: prevents a common Railway deployment issue. AI rule: 'Include deployment-platform-specific rules in the CLAUDE.md. The AI generates deployment-compatible code from the start.'

โš ๏ธ Handle SIGTERM for Zero-Downtime Railway Deployments

Railway sends SIGTERM to the container before stopping it. If the application ignores SIGTERM: Railway waits 10 seconds then sends SIGKILL (forceful termination). Active requests: dropped. Database connections: not closed properly. With SIGTERM handling: the application stops accepting new requests, finishes active requests (within a timeout), closes database connections, and exits cleanly. Your CLAUDE.md should include: 'Handle SIGTERM: graceful shutdown with active request drainage and connection cleanup.'

Step 3: Backend-Specific Rule Considerations

Railway projects are typically backend services. The AI rules: should emphasize backend patterns over frontend patterns. Key backend rules for Railway deployments: health check endpoint (Railway uses health checks to determine if the service is ready), graceful shutdown (handle SIGTERM for zero-downtime deployments โ€” Railway sends SIGTERM before stopping the container), environment variables (Railway injects DATABASE_URL, REDIS_URL, and other service connection strings โ€” the application reads from environment), and logging (structured JSON logs โ€” Railway aggregates logs from all services).

Database integration: Railway provides managed PostgreSQL, MySQL, Redis, and MongoDB. Connection strings: injected as environment variables. The AI rules should include: 'Database connection: read from process.env.DATABASE_URL (or the relevant environment variable). Never hardcode connection strings. Use connection pooling appropriate for the deployment model (Railway containers may scale โ€” share a pool, do not create per-request connections).'

Service-to-service communication: Railway projects often consist of multiple services (API, worker, scheduler) communicating over the internal network. AI rules for Railway services: 'Internal service URLs: read from environment variables (process.env.WORKER_URL). Use Railway's internal networking for service-to-service calls (private network, no public internet traversal). Include retry logic with exponential backoff for internal service calls.' AI rule: 'Railway-specific rules complement the general backend rules. They encode the deployment environment's conventions so the AI generates Railway-compatible code from the first prompt.'

โ„น๏ธ Railway-Specific Rules Complement General Backend Rules

General backend rules: API design, error handling, database patterns. Railway-specific rules: health check endpoint (Railway needs it), SIGTERM handling (Railway sends it), PORT from environment (Railway assigns it), and internal networking (Railway provides it). Both layers are needed. General rules: apply to any backend. Railway rules: make the backend Railway-compatible. The combination: generates code that works correctly on Railway from the first deployment.

Railway AI Rules Summary

Complete Railway AI rules sync setup.

  • Nixpacks: prebuild script in package.json. Same approach as Vercel and Netlify
  • Python/Go: validation in railway.toml buildCommand. Validate rules โ†’ then build the app
  • Dockerfile: validation as first build stage. Fails fast, saves build time on invalid rules
  • Health check: include /health endpoint rule. Railway uses it for readiness detection
  • Graceful shutdown: handle SIGTERM rule. Railway sends SIGTERM before stopping containers
  • Environment variables: DATABASE_URL, REDIS_URL from Railway. Never hardcode connection strings
  • Logging: structured JSON rule. Railway aggregates logs from all services
  • Internal networking: private URLs from environment variables. Retry with backoff for internal calls