Technology Stack Decision Record
Every technology choice, with explicit rationale. Nothing was chosen by default.
Table of Contents
- 3.1 Component Decision Table
- 3.2 EKS vs ECS — Infrastructure Decision
- 3.3 Go — Two Deliberate Use Cases
- 3.4 Open Decisions
3.1 Component Decision Table
| Component | Technology | Decision Rationale |
|---|---|---|
| Web UI | React | Industry standard for operator-facing SPA; rich ecosystem; component libraries (Ant Design / MUI) production-ready for business applications |
| Mobile UI | React Native | Code-share with React web (~60–70% shared logic); single team can maintain both; preferred over Flutter for JS/TS-first teams |
| API — Workspace BFF | Spring Boot + GraphQL | GraphQL enables flexible, role-aware queries from the workspace; avoids over-fetching on complex case detail views; Spring for GraphQL (DGS) is production-grade |
| API — External/Mobile | Spring Boot + REST | Standard REST with OpenAPI 3.0 for external channel intake and mobile; simpler than GraphQL for point-to-point integrations |
| Workflow Engine | Temporal.io | Purpose-built for long-running durable workflows (onboarding spans days–weeks); replays on failure; signal-based human task pattern; Typescript and Java SDKs available; production-proven at Stripe, Coinbase, Netflix |
| Agentic Framework | TBD — Python / FastAPI service | Framework selection deferred to implementation phase. Candidates: LangChain (mature, broad toolchain), LangGraph (graph-based multi-agent orchestration), Anthropic APIs direct (Claude tool use / agent patterns), OpenAI APIs direct (Assistants API / function calling). Python is confirmed; FastAPI is confirmed; LLM provider and orchestration framework will be decided when build begins. |
| Integration Broker | Spring Boot microservices | One dedicated adapter service per external system boundary; Spring’s RestClient + Resilience4j (circuit breaker + retry); OpenAPI-generated client stubs |
| Primary Database | Amazon Aurora PostgreSQL | Fully managed; PostgreSQL-compatible (standard SQL, JSON support, pgvector for AI embeddings); Aurora-specific features: fast failover, read replicas, Serverless v2 for variable load; serves as both app DB and Temporal persistence backend |
| Document Storage | Amazon S3 | Standard object storage; pre-signed URLs for secure document upload from React UI; lifecycle policies for retention; integrates with document processing pipeline |
| Cache / Session | Amazon ElastiCache (Redis) | Session state; agent working memory (short-term context across AI Assistant conversation turns); distributed lock for concurrent workflow operations |
| Container Orchestration | Amazon EKS | See §3.2 below |
| Service Mesh | AWS App Mesh (Envoy) | mTLS between services; traffic management; observability (Datadog / CloudWatch integration) |
| CI/CD | GitHub Actions + ArgoCD | GitOps deployment to EKS; Helm chart management |
| Java Runtime | Java 25 LTS | Latest LTS release (September 2025); virtual threads (Project Loom) for high-concurrency Temporal worker execution; Spring Boot 3.x requires Java 17+ and fully supports Java 25 |
3.2 EKS vs ECS — Infrastructure Decision
Recommendation: Amazon EKS (Kubernetes)
| Factor | EKS | ECS | Decision Basis |
|---|---|---|---|
| Temporal.io deployment | Official Helm chart + Kubernetes operator | Manual Docker Compose equivalent only | EKS wins — Temporal is designed for K8s |
| Service complexity | ~12 microservices at target state | Same | EKS handles this better — Helm + namespaces |
| Autoscaling | KEDA (event-driven) + HPA | ECS service autoscaling | EKS wins — KEDA can scale Temporal workers based on queue depth |
| Ecosystem | Helm, ArgoCD, Prometheus, Grafana | AWS-native tooling only | EKS wins — open-source toolchain |
| Operational complexity | Higher (requires Kubernetes expertise) | Lower | ECS advantage — but acceptable trade-off |
| Portability | Cloud-agnostic | AWS-only | EKS wins — avoids vendor lock-in |
| Cost | EKS control plane ($0.10/hr) + nodes | ECS control plane free | ECS slightly cheaper, but negligible at scale |
Verdict: EKS. Temporal.io’s Kubernetes operator, KEDA-based worker autoscaling, and the richness of the Helm/GitOps ecosystem outweigh the operational complexity premium. The long-running workflow nature of this system — individual cases lasting hours to days — requires the scalability controls that Kubernetes provides.
3.3 Go — Two Deliberate Use Cases
Go is added to the stack for two specific components where its characteristics are a genuine fit. The principle: each language is chosen because it is the right tool, not for portfolio variety.
anchita-cli — Platform Operations CLI
Every production cloud-native platform has a CLI. The Temporal server itself ships one. So does kubectl, helm, argocd. Go is the gold standard for CLI tooling:
- Single static binary — no JVM, no virtualenv, no runtime dependency. One file, runs anywhere.
- Instant startup — milliseconds vs 8–15 seconds for a Spring Boot app
- Cross-platform —
GOOS=darwin/linux/windows go buildproduces native binaries for all platforms - Rich CLI ecosystem —
cobra(command structure),viper(config),tablewriter(formatted output)
anchita cases list --segment=ENTERPRISE --status=COMPLIANCE
anchita cases show CASE-2026-042
anchita workflow signal CASE-2026-042 --signal=submitErrorRecovery --action=RETRY
anchita workers status
anchita admin product-catalog list
The CLI communicates with the existing REST API — clean boundary, no new backend logic required.
Notification Service — Real-Time WebSocket Hub
The notification-service pushes real-time updates to the React workspace (case stage changes, AI suggestions arriving, task assignments). This is a high-concurrency, low-compute workload — exactly where Go’s goroutine model wins over Spring Boot’s thread-per-connection model:
| Spring Boot (WebFlux) | Go | |
|---|---|---|
| 10,000 concurrent WebSocket connections | Complex reactive programming model | 10,000 goroutines · ~2KB stack each · ~80MB total RAM |
| Startup time | 8–15 seconds | < 500ms |
| Binary size | 80MB JAR + JVM | ~12MB static binary |
| Programming model | Reactive/non-blocking (steep learning curve) | Simple blocking goroutines (readable, testable) |
The Go notification service subscribes to Aurora NOTIFY events (PostgreSQL pub/sub) and pushes updates to connected React clients over WebSocket. Stateless, horizontally scalable, replaces the Spring Boot notification-service in the platform namespace.
Polyglot Summary
| Language | Components | Reason |
|---|---|---|
| Java 25 | Temporal workflows · Spring Boot APIs · Integration adapters | Deep ecosystem · Virtual threads · OpenAPI toolchain |
| Python 3 | AI agent service · LLM toolchain | Native ML/AI ecosystem |
| Go | anchita-cli · Notification Service |
Single binary for CLI · Goroutine concurrency for WebSocket hub |
3.4 Open Decisions
Several technology choices are intentionally deferred to implementation phase. See Open Questions for the full list. Key deferred decisions:
| Decision | Options | Preference |
|---|---|---|
| LLM provider for AI Assistant | OpenAI GPT-4o · Anthropic Claude · AWS Bedrock · Self-hosted | AWS Bedrock preferred — data sovereignty |
| Temporal Cloud vs self-hosted | Temporal Cloud (SaaS) · Self-hosted on EKS | Same SDK either way; no decision yet |
| Aurora Serverless v2 vs provisioned | Serverless v2 · Provisioned | Serverless v2 for temporal-db (bursty); provisioned for platform-db |
| Agentic framework | LangChain · LangGraph · Anthropic APIs direct · OpenAI APIs | Deferred — Python + FastAPI confirmed |