Skip to content

Infrastructure

Current Stack (Railway — Staging)

Infrastructure Services

ServiceRoleNotes
PostgreSQLPrimary database (Railway managed)Two databases: finance, mgmt. Multi-schema.
RustFSS3-compatible object storageSelf-hosted on Railway. Access via BLOBACCESSKEY/BLOBSECRETKEY.
ValkeyRedis-compatible cacheSession cache
TemporalWorkflow orchestration engineSelf-hosted on Railway
Temporal UITemporal dashboardRailway internal
RabbitMQ 4Message brokerAMQP (port 5672) and Streams (port 5552) — both in use
Debezium ServerCDC pipelineWatches 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.

FilePurpose
shared/config.tsRailway project configuration
shared/databases.tsInfra service definitions (Postgres, RustFS, Valkey, Temporal)
shared/variables.tsShared environment variable definitions
shared/railway-client.tsRailway GraphQL API client
backend/infrastructure.tsMicroservice definitions
frontend/infrastructure.tsFrontend 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)

WorkflowTriggerPurpose
provision.ymlManualProvision Railway infra
deploy-staging.ymlManualDeploy to staging
deploy-production.ymlManual (env approval)Deploy to production
scale-staging.ymlManual + daily scheduleScale 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:

ProtocolPortServicesAWS Compatibility
AMQP (classic queues)5672queue, events, wfwAmazon MQ ✅
RabbitMQ Streams5552@blitz/lib-streamAmazon 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 EquivalentMigration Effort
Railway PostgreSQLRDS PostgreSQL 16 (Multi-AZ, db.t3.medium)Medium
ValkeyElastiCache Redis 7 (cache.t3.micro)Low
RustFSAmazon S3Low
RabbitMQ AMQPAmazon MQ (RabbitMQ)Low
RabbitMQ StreamsSelf-hosted RabbitMQ on ECS (if needed)Medium
Debezium ServerECS Fargate task (new)Medium
Temporal (self-hosted)Temporal Cloud (recommended)Medium
Docker microservicesECS Fargate (one service per microservice)Medium
nginx / Railway routingALB (Application Load Balancer)Low
blitz-ui static buildS3 + CloudFrontMedium
Railway env varsAWS Secrets Manager + SSM Parameter StoreLow
fin-infra/railway/ scriptsfin-infra/aws/ (CDK or Terraform, TBD)Medium

Target Networking

  • VPC: 10.0.0.0/16 in 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:

  1. Build and deploy 5 remote apps (closehub, invoice, journal, recon, collections) to S3
  2. Determine their CloudFront URLs
  3. Set VITE_*_REMOTE_URL env vars
  4. Build and deploy the ui host 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

PhaseScope
1 — FoundationVPC, RDS, S3, Secrets Manager, IAM Identity Center, Zoho SSO
2 — DataMigrate PostgreSQL to RDS, RustFS buckets to S3
3 — ComputeECS Fargate cluster, ALB, Debezium CDC task, CloudFront
4 — MessagingAmazon MQ, ElastiCache, Temporal Cloud (after Streams decision)
5 — CutoverRoute 53 DNS → ALB/CloudFront, Railway decommission
6 — ObservabilityCloudWatch, Container Insights, X-Ray, SNS alerts
7 — SecurityWAF, GuardDuty, Config rules, KMS, VPC Flow Logs

Estimated Monthly Cost (ap-south-1, 6 services)

ServiceEst. 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