Infrastructure
Current Stack (Railway — Staging)
Infrastructure Services
| Service | Role | Notes |
|---|---|---|
| PostgreSQL | Primary database (Railway managed) | Two databases: finance, mgmt. Multi-schema. |
| RustFS | S3-compatible object storage | Self-hosted on Railway. Access via BLOBACCESSKEY/BLOBSECRETKEY. |
| Valkey | Redis-compatible cache | Session cache |
| Temporal | Workflow orchestration engine | Self-hosted on Railway |
| Temporal UI | Temporal dashboard | Railway internal |
| RabbitMQ 4 | Message broker | AMQP (port 5672) and Streams (port 5552) — both in use |
| Debezium Server | CDC pipeline | Watches Postgres WAL, publishes change events to RabbitMQ objectevents_exchange (fanout) |
IaC Code (fin-infra/railway/)
The railway/ directory contains TypeScript scripts that call the Railway GraphQL API directly — no Terraform or Docker Compose.
| File | Purpose |
|---|---|
shared/config.ts | Railway project configuration |
shared/databases.ts | Infra service definitions (Postgres, RustFS, Valkey, Temporal) |
shared/variables.ts | Shared environment variable definitions |
shared/railway-client.ts | Railway GraphQL API client |
backend/infrastructure.ts | Microservice definitions |
frontend/infrastructure.ts | Frontend service definition |
scripts/ | Provision, deploy, vars, scale, logs, status, init-db |
Railway API limitation: ${{service.VAR}} variable references do not work via the GraphQL API. All inter-service communication uses static .railway.internal hostnames instead.
Container Registry
All images are stored in GHCR (ghcr.io/finaisse-org/):
- Tags:
latest(main branch),:<short-sha>(all commits),:<branch-slug>(non-main)
CI/CD (GitHub Actions — fin-infra)
| Workflow | Trigger | Purpose |
|---|---|---|
provision.yml | Manual | Provision Railway infra |
deploy-staging.yml | Manual | Deploy to staging |
deploy-production.yml | Manual (env approval) | Deploy to production |
scale-staging.yml | Manual + daily schedule | Scale staging; auto-down at 10:30 PM IST |
Networking (Railway)
Services communicate over Railway's internal network using .railway.internal hostnames. No public IPs on infra services.
RabbitMQ Usage
The stack uses RabbitMQ in two distinct protocols:
| Protocol | Port | Services | AWS Compatibility |
|---|---|---|---|
| AMQP (classic queues) | 5672 | queue, events, wfw | Amazon MQ ✅ |
| RabbitMQ Streams | 5552 | @blitz/lib-stream | Amazon MQ ❌ |
This Streams incompatibility is a blocking constraint for the AWS migration. See Gaps.
AWS Migration
Status: Planned, not started. Draft v2 plan prepared May 2026.
Target region: ap-south-1 (Mumbai)
AWS Service Mapping
| Current (Railway) | AWS Equivalent | Migration Effort |
|---|---|---|
| Railway PostgreSQL | RDS PostgreSQL 16 (Multi-AZ, db.t3.medium) | Medium |
| Valkey | ElastiCache Redis 7 (cache.t3.micro) | Low |
| RustFS | Amazon S3 | Low |
| RabbitMQ AMQP | Amazon MQ (RabbitMQ) | Low |
| RabbitMQ Streams | Self-hosted RabbitMQ on ECS (if needed) | Medium |
| Debezium Server | ECS Fargate task (new) | Medium |
| Temporal (self-hosted) | Temporal Cloud (recommended) | Medium |
| Docker microservices | ECS Fargate (one service per microservice) | Medium |
| nginx / Railway routing | ALB (Application Load Balancer) | Low |
| blitz-ui static build | S3 + CloudFront | Medium |
| Railway env vars | AWS Secrets Manager + SSM Parameter Store | Low |
| fin-infra/railway/ scripts | fin-infra/aws/ (CDK or Terraform, TBD) | Medium |
Target Networking
- VPC:
10.0.0.0/16in ap-south-1 - Public subnets (2 AZs): ALB, NAT Gateway
- Private subnets (2 AZs): ECS Fargate, ElastiCache, Amazon MQ, Temporal
- DB subnets (2 AZs): RDS Multi-AZ (isolated)
Memory Sizing Exception
wfw requires minimum 1 GB RAM — OOM confirmed at 512 MB. All other services: 512 MB.
Frontend on AWS
Module Federation requires all 6 sub-apps to be built and deployed in order:
- Build and deploy 5 remote apps (closehub, invoice, journal, recon, collections) to S3
- Determine their CloudFront URLs
- Set
VITE_*_REMOTE_URLenv vars - Build and deploy the
uihost app with those URLs baked in
Infrastructure: S3 bucket per sub-app (or path-based), single CloudFront distribution, ACM cert, Route 53.
Secrets Strategy
- AWS Secrets Manager (~20 secrets, ~$8/month): credentials that rotate —
JWTSECRET,DATABASE_URL,RABBITMQ_URL,BLOBACCESSKEY/BLOBSECRETKEY, API keys - SSM Parameter Store (~80 params, effectively free): non-secret config — infrastructure endpoints, AI model selection, feature flags, tuning parameters
Identity
Zoho is used as the SAML 2.0 IdP for AWS IAM Identity Center. GitHub Actions OIDC is used for IaC pipelines — no long-lived AWS keys in GitHub secrets.
Phased Migration Plan
| Phase | Scope |
|---|---|
| 1 — Foundation | VPC, RDS, S3, Secrets Manager, IAM Identity Center, Zoho SSO |
| 2 — Data | Migrate PostgreSQL to RDS, RustFS buckets to S3 |
| 3 — Compute | ECS Fargate cluster, ALB, Debezium CDC task, CloudFront |
| 4 — Messaging | Amazon MQ, ElastiCache, Temporal Cloud (after Streams decision) |
| 5 — Cutover | Route 53 DNS → ALB/CloudFront, Railway decommission |
| 6 — Observability | CloudWatch, Container Insights, X-Ray, SNS alerts |
| 7 — Security | WAF, GuardDuty, Config rules, KMS, VPC Flow Logs |
Estimated Monthly Cost (ap-south-1, 6 services)
| Service | Est. USD/month |
|---|---|
| RDS PostgreSQL (db.t3.medium, Multi-AZ) | $80–$120 |
| ECS Fargate (6 services) | $100–$180 |
| Amazon MQ (mq.t3.micro) | $30–$50 |
| ElastiCache (cache.t3.micro) | $20–$30 |
| ALB | $20–$30 |
| CloudFront + S3 | $10–$30 |
| Secrets Manager | $8–$12 |
| CloudWatch | $15–$30 |
| NAT Gateway | $30–$50 |
| Temporal Cloud (starter) | $0–$25 |
| Total | $313–$557 |