Finaisse / Blitz Platform
AWS Infrastructure Mapping & Architecture Recommendation
Prepared by: Sekhar Prakash
Date: May 2026
Status: Draft v3 — updated June 2026: Terraform confirmed, RabbitMQ removed (Temporal-only workflows), GHCR confirmed, service count corrected to 16
1. Purpose & Scope
This document maps the current Finaisse production stack (blitz backend, blitz-ui frontend) to equivalent AWS managed services. It serves as the foundation for the AWS infrastructure setup.
The Railway platform will continue to host the staging environment while AWS production infrastructure is built out in phases. US and EU regions are out of scope for this phase and will be addressed based on customer data-residency requirements.
Changes from v2: IaC tooling confirmed as Terraform (multi-cloud scope — AWS + Cloudflare + future Gemini/GCP). RabbitMQ removed — all async workflows are Temporal-managed. Container registry confirmed as GHCR (unchanged). Service count corrected from 6 → 16 (reflects current Railway staging state). Debezium CDC pipeline removed (RabbitMQ dependency eliminated).
2. Current Stack Overview
2.1 Backend — blitz
Runtime: Bun. Framework: Elysia. ORM: Prisma. Language: TypeScript.
The backend is a microservices monorepo. Each service is independently containerised. The API gateway (api, port 10001) is the single entry point for all client traffic.
16 services are targeted for AWS production — 4 infrastructure services and 12 application services, matching the current Railway staging environment.
Infrastructure services (4) — AWS managed equivalents replace these
| Service (Railway name) | Current | AWS equivalent |
|---|---|---|
| blitz-db | Railway managed PostgreSQL | RDS PostgreSQL 16 Multi-AZ |
| blitz-s3 | RustFS (S3-compatible, self-hosted) | Amazon S3 |
| blitz-temporal | Temporal (self-hosted on Railway) | Temporal Cloud |
| blitz-valkey | Railway Valkey | ElastiCache Redis 7 |
Temporal UI (blitz-temporal-ui) runs as a sidecar to Temporal. On AWS, this is provided by Temporal Cloud's built-in UI — no separate deployment needed.
Application services (12) — deployed to ECS Fargate on AWS
| Service | Port | Role | Notes |
|---|---|---|---|
| blitz-api | 10001 | API gateway — single entry point for all clients | Public-facing via ALB |
| blitz-ws | 10002 | WebSocket server for real-time features | |
| blitz-agents | 10013 | AI agent execution | Sleeping in staging (scale-down) |
| blitz-excelrw | 10014 | Excel read/write (.NET-based) | |
| blitz-emailprocessor | — | Async email processing worker | No HTTP port |
| blitz-wfw | — | Temporal workflow worker | Minimum 1 GB RAM — OOM at 512 MB; runs system, closehub, cash, coresystem, invoice workers in parallel |
| blitz-wfwpdf | — | Temporal PDF workflow worker | Built in GHCR; not yet in Railway staging — add to AWS directly |
| blitz-recon | 10015 | Reconciliation service | Sleeping in staging (scale-down) |
| blitz-remotecontrol | 10016 | Remote control worker | |
| blitz-classicml | — | Classic ML inference (Python Temporal worker) | No HTTP port; task queues: taskqueue-system-ml-training, taskqueue-system-ml-inference |
| blitz-ui | — | Vue 3 Module Federation frontend shell | S3 + CloudFront, not ECS |
Note: blitz-ui is a static frontend — it is served from S3 + CloudFront, not as an ECS service. See Section 5.5.
Services in the monorepo NOT targeted for initial AWS launch
| Service | Port | Status |
|---|---|---|
| apimgmt | 9999 | Not yet deployed |
| queue | 10008 | Not yet deployed |
| events | 10009 | Not yet deployed |
| pdfwriter | 10011 | Not yet deployed |
| fs | 10010 | Not yet deployed |
| rulesengine | 10006 | Not yet deployed |
| mcp | 10012 | Not yet deployed |
| scriptrunner | 10003 | Not yet deployed |
| jsontransformer | 10004 | Not yet deployed |
| templaterenderer | 10005 | Not yet deployed |
| 10007 | Not yet deployed | |
| jobs | — | Overlap with queue unclear — needs review |
| desktop | — | Electron app — not an ECS candidate |
2.2 Frontend — blitz-ui
Framework: Vue 3.5 with Composition API. Build tool: Vite 7. Runtime: Bun. UI library: Vuetify 3 + Syncfusion EJ2.
The frontend is a multi-app monorepo using Module Federation. Each sub-application is built independently and the main ui shell dynamically loads the others at runtime via URLs baked in at build time.
| App | Dev Port | Description |
|---|---|---|
| ui | 10000 | Main application shell (host app) |
| closehub | 5001 | Close Hub standalone app (remote) |
| invoice | 5005 | Invoice management (remote) |
| journal | 5003 | Journal entries (remote) |
| recon | 5004 | Reconciliation (remote) |
| collections | 5002 | Collections management (remote) |
Module Federation note: The URLs for each remote app are injected via VITE_*_REMOTE_URL environment variables and compiled into the JavaScript bundle at build time. They cannot be changed without rebuilding. On AWS, these must resolve to the final CloudFront URLs before the build runs — all 6 apps must be built and deployed in a coordinated pipeline.
2.3 Infrastructure — current (Railway)
| Component | Current solution | Notes |
|---|---|---|
| PostgreSQL | Railway managed PostgreSQL | Two databases: finance, mgmt. Multi-schema design. |
| Redis / Valkey | Railway Valkey | Session cache |
| Object storage | RustFS (S3-compatible) | S3-compatible API. Used via BLOBACCESSKEY/BLOBSECRETKEY. |
| Workflow engine | Temporal (Railway self-hosted) | Used by wfw and wfwpdf. |
| Message broker | None (removed) | RabbitMQ eliminated — all async work is Temporal-managed. |
| Secrets | Railway environment variables | JWT secret, DB credentials, API keys. |
| Container registry | GHCR (GitHub) | Images tagged :latest and :<short-sha>. Confirmed — no migration to ECR. |
| CI/CD | GitHub Actions | Build, push, deploy workflows in fin-infra. |
| IaC | fin-infra/railway/ (Bun + TypeScript) | Provision, deploy, variable sync scripts. |
3. IaC Tooling — Terraform (Confirmed)
Decision: Terraform (HCL)
Rationale: Multi-cloud scope requires a single IaC tool that manages AWS, Cloudflare (Pages, DNS, Zero Trust already in use), and future GCP/Gemini infrastructure. Terraform is the only realistic choice for this breadth.
The fin-infra/aws/ folder will sit alongside the existing fin-infra/railway/ folder.
| Dimension | Decision |
|---|---|
| Tool | Terraform |
| State backend | S3 bucket + DynamoDB lock table (ap-south-1) |
| Providers | hashicorp/aws, cloudflare/cloudflare, hashicorp/google (future) |
| Workspace layout | fin-infra/aws/ — modules per layer (networking, data, compute, frontend) |
| CI/CD | GitHub Actions with OIDC — no long-lived AWS keys in secrets |
4. AWS Service Mapping
| Current | AWS equivalent | Migration effort | Notes |
|---|---|---|---|
| Railway PostgreSQL | RDS PostgreSQL 16 (Multi-AZ) | Medium | db.t3.medium. Same Prisma schemas, connection string change only. |
| Railway Valkey | ElastiCache (Redis 7) | Low | cache.t3.micro. Drop-in replacement — same Redis protocol. |
| RustFS (S3-compatible) | Amazon S3 | Low | S3-compatible API. Endpoint and credential env var change only. Replace BLOB_HOST/BLOB_PORT with S3 endpoint. |
| Temporal (Railway self-hosted) | Temporal Cloud | Medium | Temporal Cloud free starter tier for initial launch. Revisit self-hosted at scale. |
| Microservices (Docker) | ECS Fargate | Medium | One ECS service per application service (12 services). Existing Docker images work as-is. wfw needs ≥1 GB task memory. |
| nginx / Railway routing | ALB (Application Load Balancer) | Low | Path/host-based routing replaces nginx. |
| blitz-ui static build | S3 + CloudFront | Medium | Vite build output per sub-app. Module Federation remote URLs must be set before build. Coordinated 6-app build pipeline required. |
| GHCR registry | GHCR (unchanged) | None | Confirmed — no migration. |
| GitHub Actions | GitHub Actions (unchanged) | Low | Deploy step changes from Railway API call to ECS update-service call. |
| RabbitMQ | Removed | — | All async workflows managed by Temporal. No messaging layer needed. |
| fin-infra/railway/ scripts | fin-infra/aws/ (Terraform) | Medium | Same repo, new folder. Multi-cloud: AWS + Cloudflare + GCP (future). |
5. Target AWS Architecture
5.1 Region Selection
Primary region: ap-south-1 (Mumbai)
| Factor | Mumbai (ap-south-1) | Hyderabad (ap-south-2) |
|---|---|---|
| Available since | 2016 | 2022 |
| Service coverage | Full — all required services available | Partial — some services still rolling out |
| Latency from major Indian cities | 5–15 ms | 8–20 ms |
| Recommendation | Primary production region | DR / backup target once stable |
US and EU regions will be provisioned later using the same Terraform code with environment parameters.
5.2 Networking
- VPC:
10.0.0.0/16in ap-south-1 - Public subnets (2 AZs): ALB, NAT Gateway
- Private subnets (2 AZs): ECS Fargate tasks, ElastiCache, Temporal
- DB subnets (2 AZs): RDS Multi-AZ, isolated subnet group
- All inter-service communication over private DNS — no public IPs on services
5.3 Compute — ECS Fargate
Each application microservice runs as an independent ECS service within a single ECS cluster.
- Cluster:
finaisse-prod - Task definitions: one per service, referencing GHCR images
- Service discovery: AWS Cloud Map for internal service-to-service calls
- Auto-scaling: target tracking on CPU/memory per service
- Existing Docker images require no changes — only environment variable injection changes
Memory sizing exceptions:
| Service | Minimum task memory | Reason |
|---|---|---|
| blitz-wfw | 1024 MB (1 GB) | Runs 5 Temporal workers in parallel + S3/tenancy init. OOM confirmed at 512 MB. |
| All others | 512 MB | Standard sizing |
5.4 Data Layer
| Service | AWS resource | Config |
|---|---|---|
| PostgreSQL | RDS PostgreSQL 16, Multi-AZ | db.t3.medium, 100 GB gp3, automated backups 7 days, encryption at rest |
| Redis / Valkey | ElastiCache Redis 7 | cache.t3.micro, single-AZ for start, upgrade to cluster mode later |
| Object storage | Amazon S3 | Versioning enabled, SSE-S3, lifecycle rules for old versions |
| Workflow engine | Temporal Cloud | Recommended for initial launch; revisit self-hosted at scale |
| Secrets | AWS Secrets Manager + SSM Parameter Store | See Section 6 |
5.5 Frontend Delivery
The blitz-ui frontend uses Module Federation. The deployment pipeline must:
- Build and deploy all 5 remote apps (closehub, invoice, journal, recon, collections) to their S3 prefixes first
- Determine their CloudFront URLs
- Set
VITE_*_REMOTE_URLenv vars pointing to those CloudFront URLs - Build and deploy the
uihost app with those URLs baked in
Infrastructure:
- One S3 bucket with path-based prefixes per sub-app (or separate buckets)
- Single CloudFront distribution with path-based origin routing
- ACM certificate (free) for TLS at CloudFront
- Cloudflare DNS for
app.finaisse.com→ CloudFront (Cloudflare already manages finaisse.com DNS) - WAF attached to CloudFront for rate limiting and basic bot protection
This static S3+CloudFront model works for blitz-ui because its backend (blitz-api) is public-facing via ALB — the browser calls the API directly (the nginx /api proxy is replaced by ALB path routing). The pattern requires a publicly-reachable backend.
5.5.1 Management Portal (apimgmt + mgmt UI) — does NOT fit the standard pattern
The tenant-onboarding admin portal cannot use the same "static S3 + public ALB" approach, because apimgmt must stay private (superadmin API; holds tenant DB connection strings — never publicly exposed). Not yet reflected in the service mapping above (this work post-dates the doc). When added to the AWS plan:
- apimgmt → ECS Fargate service on an internal-only target group (not a public ALB listener). No public route.
- mgmt UI → must reach that private backend, so it needs an in-network proxy — i.e. it stays a container (nginx) on ECS that proxies
/api→ the internal apimgmt target, OR a static site fronted by an internal ALB that only an authenticated edge can reach. It does NOT get a plain public S3+CloudFront origin that talks to a public apimgmt. - Admin access → gate the mgmt UI hostname (
mgmt.finaisse.com) with Cloudflare Access (admins-only policy; WARP SSO), keeping apimgmt non-public. Thex-mgmt-api-keyguard remains the inner layer.
Net: the main UI can go fully static because its API is public by design; the mgmt UI cannot, because its API is private by design. Tracking: blitz#898 (deploy wiring), blitz#885 (per-tenant DB provisioning).
6. Secrets & Environment Variables
The stack uses 100+ environment variables across services. These split into two AWS storage tiers:
AWS Secrets Manager (~20 secrets, ~$8/month)
Actual credentials that should be rotated and audited:
| Secret | Services |
|---|---|
JWTSECRET | All backend |
DATABASE_URL, MANAGEMENT_DATABASE_URL | All backend |
DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_PORT | All backend |
BLOBACCESSKEY, BLOBSECRETKEY | All backend (file ops) |
GOOGLE_API_KEY | agents, wfw, docai services |
OPENAI_API_KEY | agents |
LLAMA_CLOUD_API_KEY | agents |
VITE_SYNCFUSION_LICENSEKEY | blitz-ui build only |
MINDSDB_MCP_ACCESS_TOKEN | mcp |
SENTRY_DSN | All backend services + blitz-ui |
SSM Parameter Store (~80 params, effectively free)
Non-secret configuration that changes between environments:
| Category | Example vars |
|---|---|
| Infrastructure endpoints | BLOB_HOST, BLOB_PORT, TEMPORAL_HOST, TEMPORAL_PORT, REDIS_URL |
| AI model selection | GEMINI_MODEL_NAME, GEMINI_DOCAI_MODEL, DEFAULT_MODEL, DEFAULT_CHAT_MODEL, all DEFAULT_*_MODEL vars |
| Google Cloud config | GOOGLE_CLOUD_PROJECT_ID, GOOGLE_CLOUD_LOCATION, GOOGLE_DOCUMENT_AI_PROCESSOR_ID |
| CID matching tuning | ~19 CID_* vars (thresholds, confidence levels) |
| Reconciliation tuning | ~23 MATCHING_* vars |
| Cash app config | CASHAPP_BULK_ENABLED, CASHAPP_BULK_BATCH_SIZE, CASHAPP_CREATE_JOURNAL |
| Feature flags | TENANCY_ENABLED, NODE_ENV, DEFAULT_LOGLEVEL |
| Queue names | CDCEVENTS_QUEUE_NAME, EVENTS_QUEUE_NAME, JOBSEXECUTION_QUEUE_NAME |
| Integrations | RC_SERVER_URL, RC_API_KEY, MCP_SERVER_URL, CDG_API_URL |
7. Identity & Access — Zoho as SSO/IdP for AWS
Zoho can be used as the SAML 2.0 identity provider for AWS IAM Identity Center (formerly AWS SSO). This is the recommended setup for a team already using Zoho.
How it works
AWS IAM Identity Center federates with Zoho Directory via SAML 2.0. Once configured, the Zoho login page becomes the entry point for AWS console access. You assign Zoho users or groups to AWS accounts and permission sets from the IAM Identity Center console.
What happens to your existing root account password login
- The root account (created with your email + password) is never federated — it stays as-is and is used only for break-glass situations (billing, account recovery, disabling IAM Identity Center itself). AWS best practice: remove MFA-less root access, store root credentials in a vault, and never use it day-to-day.
- All day-to-day console access moves to IAM Identity Center → Zoho SSO. Team members log in at your IAM Identity Center URL (e.g.
finaisse.awsapps.com/start) using their Zoho credentials. - Your personal root email + password continues to work as a fallback but should never be the normal path.
Setup steps (high level)
- Enable IAM Identity Center in ap-south-1 (or us-east-1 — it's a global service, pick one region).
- In Zoho Directory, add AWS as a SAML application — Zoho has a pre-built AWS template.
- Exchange SAML metadata between Zoho and IAM Identity Center.
- Create Permission Sets in IAM Identity Center (e.g.
AdministratorAccessfor Sekhar,ReadOnlyfor others). - Assign Zoho users/groups to the AWS prod account with those permission sets.
- Team accesses AWS via the IAM Identity Center portal URL using Zoho credentials.
GitHub Actions OIDC
Terraform pipelines in GitHub Actions must use IAM roles assumed via OIDC — no long-lived AWS access keys in GitHub secrets. This applies to all three cloud providers (AWS OIDC, Cloudflare API token via Actions secret, GCP Workload Identity Federation when needed).
8. Phased Migration Plan
Railway staging continues to run throughout. Each phase is independently deployable and reversible before the final DNS cutover.
| Phase | Scope | Key activities |
|---|---|---|
| 1 — Foundation | Networking + data layer | VPC, subnets, security groups, RDS, S3, Secrets Manager, SSM Parameter Store, IAM roles, IAM Identity Center + Zoho SSO. Terraform state backend (S3 + DynamoDB). IaC only — no application traffic. |
| 2 — Data migration | PostgreSQL + RustFS → S3 | Migrate Railway PostgreSQL to RDS. Validate Prisma connections. Migrate RustFS buckets to S3. Run parallel briefly. |
| 3 — Compute | ECS Fargate + ALB | ECS cluster, task definitions for all 12 application services, ALB listener rules. Run parallel with Railway. |
| 4 — Workflows | Temporal Cloud | Cut over wfw and wfwpdf to Temporal Cloud. Validate all workflow task queues. ElastiCache cutover. |
| 5 — Frontend | S3 + CloudFront | Coordinated 6-app Module Federation build and deploy. Cloudflare DNS points app.finaisse.com → CloudFront. |
| 6 — Cutover | DNS + Railway decommission | Final DNS cutover for API. Monitor for 1 week. Decommission Railway production. |
| 7 — Observability | Monitoring + alerting | CloudWatch Logs, Container Insights, X-Ray tracing (connect to existing OTEL_EXPORTER_URL OpenTelemetry integration), SNS alerts, dashboards per domain. Sentry error tracking across all services (see Section 10, item 10). Sentry SDK integration in blitz/blitz-ui is a pre-launch code change — must be done before Phase 6 cutover. |
| 8 — Security hardening | Compliance + hardening | WAF rules, GuardDuty, AWS Config rules, IAM least-privilege audit, KMS encryption, VPC Flow Logs. |
9. Estimated Monthly Cost (ap-south-1)
Estimates are for the 12 application services at lean production sizing.
| Service | Configuration | Est. USD/month |
|---|---|---|
| RDS PostgreSQL | db.t3.medium, Multi-AZ, 100 GB gp3 | $80–$120 |
| ECS Fargate | 12 services (wfw at 1 GB, others 512 MB) | $180–$300 |
| ElastiCache | cache.t3.micro, single-AZ | $20–$30 |
| ALB | Application Load Balancer | $20–$30 |
| CloudFront + S3 | Frontend delivery + object storage | $10–$30 |
| Secrets Manager | ~20 secrets | $8–$12 |
| SSM Parameter Store | ~80 params (standard tier) | $0 |
| CloudWatch | Logs, metrics, dashboards | $15–$30 |
| NAT Gateway | Outbound from private subnets | $30–$50 |
| Temporal Cloud | Starter tier | $0–$25 |
| Total (estimated) | $363–$627 |
Cost increases as additional services from the monorepo are brought to production.
10. Open Items & Decisions Required
| # | Item | Status |
|---|---|---|
| 1 | IaC tooling | ✅ Terraform — multi-cloud scope (AWS + Cloudflare + GCP/Gemini) |
| 2 | RabbitMQ / messaging | ✅ Removed — all async workflows are Temporal-managed |
| 3 | Container registry | ✅ GHCR — no migration to ECR |
| 4 | Service scope for AWS | ✅ 16 services (4 infra → AWS managed, 12 app → ECS Fargate + S3/CloudFront) |
| 5 | Zoho SSO | Set up IAM Identity Center + Zoho SAML before Phase 1 |
| 6 | wfwpdf staging gap | Built in GHCR but not in Railway staging — deploy directly to AWS in Phase 3 |
| 7 | jobs service | Unclear if this overlaps with queue or is separate — needs review before expanding beyond 16 |
| 8 | Ollama | Currently in compose for local LLM. On AWS, replace with Bedrock or external API endpoint. Decision needed for agents service. |
| 9 | Hyderabad DR | Confirm when to bring ap-south-2 online as a DR target |
| 10 | Sentry error tracking | Pre-launch code change required in blitz + blitz-ui before Phase 6 cutover. Create Sentry org, add @sentry/node to all Bun/Elysia services, @sentry/vue to blitz-ui, sentry-sdk to blitz-classicml (Python). One SENTRY_DSN per service or shared project with service tags. Start with Sentry cloud free tier; evaluate self-hosted Glitchtip later if data residency requires it. |
Document prepared with Claude Code (Anthropic) — Finaisse internal use only