Skip to content

ADR-001: Foundational Architecture & Technology Stack

Status

Accepted

Context

FintraOS is building a multi-tenant Financial Intelligence Platform. The system needs to ingest high-volume financial data from aggregators (initially) and direct feeds (eventually), normalise it into a unified "Financial Twin," apply real-time intelligence (Rules + ML), and expose insights via streaming APIs.

Key Requirements confirmed: - Tenancy: Multi-tenant SaaS. - Data Source: Aggregators first (Plaid, etc.) + Manual entry support. - Persistence: All events and history must be stored forever (Event Sourcing pattern). - Intelligence: Hybrid approach (Configurable Rules Engine + Baseline ML models). - Output: Event Streaming (primary) + APIs. - Domain: Personal Finance (Retail) focus initially.

Decision

1. Architecture Style: Event-Driven Microservices

We will adopt an Event-Driven Architecture (EDA). - Why: Financial data is inherently event-based (Transaction Occurred, Balance Updated, Goal Achieved). - Implementation: - FintraOS Pulse will be the central nervous system. - Services will communicate asynchronously via an Event Log (Kafka/Redpanda). - "FintraOS Views" will be Read Models (CQRS pattern) built by consuming these events.

2. Primary Data Store: Event Store (The "Vault")

  • Decision: We will use an immutable append-only log as the Source of Truth.
  • Technology: PostgreSQL (with partitioned tables for events).
  • Rationale: "We need to store everything." An audit trail is mandatory for compliance. We can replay events to train new ML models or run "What-If" Simulations (e.g., re-processing history with new savings rules).

3. Read & Search Stores

  • Read Models (Views/Core): PostgreSQL (JSONB).
    • Rationale: Relational + JSON capabilities allow for flexible document storage while maintaining strong consistency where needed.
  • Text Search (Core): ElasticSearch or OpenSearch.
    • Rationale: Full-text search for transaction descriptions.
  • Vector Search (Brain): Qdrant.
    • Rationale: High-performance vector similarity search for embeddings, enforced by AI Context Scoping policies.

4. Streaming Interface

  • Decision: External clients will consume data via Webhooks (for simple notifications) and gRPC/Serverless Streaming (for high-volume real-time feeds).
  • Rationale: "Streaming seems better." It reduces polling load and provides real-time experiences for client apps.

5. Intelligence Engine (The "Brain")

  • Decision: A multi-layer approach.
  • Layer 1 (Fast): A configurable Rules Engine (e.g., JSON-Logic or CEL) that runs on every event. Clients can define thresholds (e.g., "Alert me if spend > $500").
  • Layer 2 (Context): Global Context Providers (Inflation, Market Data) that adjust values in real-time.
  • Layer 3 (Slow/Batch): Python-based ML services running asynchronously for forecasting and classification. See Brain Spec.

6. Multi-Tenancy Strategy

  • Decision: Logic Separation (Row-level security).
  • Implementation: All data is tagged with TenantID.
  • Encryption: Tenant-specific encryption keys (Key Management Service) managed by FintraOS Guard.

Consequences

  • Complexity: Event Sourcing is harder to debug than simple CRUD. We need strong observability tools from Day 1.
  • Consistency: Views will be "Eventually Consistent." We must educate client developers that "Real-time" means "sub-second," not "instant atomic transaction."

Related: Dashboard | [[ADR-002]] | Full Architecture