Self-Hosted Personal Finance Tracking – Architecture (Actual Budget + SimpleFIN)
Decisions
Core product goals
- Self-hosted UI that feels like “old school Mint”: fast browsing of transactions, categories, budgets, and net worth.
- Reliable account connectivity for the household/business footprint: Truist, TD Bank, Chase (multiple), Amex (multiple), plus others as needed.
- Local intelligence layer for insights (spend trends, anomalies, recurring bills, forecasting) that sits atop the finance dataset without compromising data integrity.
Confirmed decisions
-
Primary solution = Actual Budget (self-hosted)
- Actual is the core UI and daily system of record for budgets, categories, payees, transactions.
-
Primary sync = SimpleFIN Bridge
- Institutions sync via SimpleFIN; refresh is on-demand/scheduled polling (not push streaming).
-
Minimize custom code
- Prefer Actual + SimpleFIN as-is. Add custom components only when justified and keep them isolated.
-
Optional “insights” sidecar (read-only)
- Insights are additive and non-destructive (no automatic edits; no credentials). Not a hard dependency.
Failure Modes (Finance)
SimpleFIN / institution sync failures
- Re-auth required (MFA, session invalidation, OAuth refresh): surface status; keep last-known data; notify operator.
- Institution outage / aggregator degradation: stagger polling; backoff retries; Actual remains usable.
- Rate limits / throttling: per-institution schedules; circuit breaker.
- Partial updates: record sync timestamps per connection; show per-account freshness.
Data correctness failures
- Duplicate transactions due to changing identifiers: canonical dedupe rules; merge/audit path.
- Payee normalization conflicts: separate suggested vs locked payees; allow safe revert.
- Posting date inconsistencies: store/show posted date and cleared semantics when supported.
Infrastructure failures
- DB/volume corruption or disk full: nightly backups + retention; storage monitoring; test restores.
- Container restart/upgrades: healthchecks + restart policies; predictable update playbook.
- Secrets exposure: secrets outside git; avoid plaintext tokens in logs; rotate credentials.
Insights layer failures (non-critical)
- LLM/analytics errors: insights cite numbers; read-only; disclaim uncertainty. Degrade silently.
Framework
Minimal target architecture
- actual-server (Actual Budget): canonical budgeting app + UI
- simplefin-bridge (external service): bank/CC connectivity for Actual’s sync integration
- reverse-proxy (NPM): TLS termination, hostname, access control via
fin.teamlewis.co - backups: automated backup/retention for Actual data volume; encrypted off-host copy
Optional add-ons (kept minimal)
- insights-sidecar (optional): periodic export → local Postgres/SQLite; dashboards/notifications
- llm-gateway (optional): read-only conversational queries over finance data
Data flow (high level)
- SimpleFIN → Actual (scheduled on-demand refresh)
- Actual (primary) → optional export → Insights DB → dashboards/notifications/LLM
Sync scheduling
- Default: refresh every 6–12 hours + on-demand "Sync now"; institution-specific backoff
Integrations
Confirmed: SimpleFIN → Actual Budget
- Covers checking/savings and credit cards (as supported).
- Outputs accounts and transactions into Actual.
Bills/subscriptions
- Primary: inferred from transaction patterns (recurring detection)
- Optional: manual bill definitions (merchant + cadence + amount range)
Notifications (optional)
- Re-auth required; no successful sync >24h; large/unusual charge; upcoming bill renewal
Crypto/brokerages (out-of-scope unless needed later)
- If needed later: Kraken via read-only API keys; brokerages via separate pipeline if SimpleFIN cannot cover
Intent
What this system is
- A local-first personal finance stack powered by Actual Budget and SimpleFIN, with optional read-only insights.
What this system is not
- Not a real-time streaming system; refresh/poll based
- Not a complex multi-aggregator ingestion platform (unless future requirements force it)
- Not an autonomous agent changing financial records without explicit user action
Primary user workflows
- Link institutions via SimpleFIN
- Sync into Actual and confirm accounts
- Categorize and create rules
- Budget and reconcile
- (Optional) Review insights and receive alerts
Naming Conventions (Finance)
Services
actual-server,reverse-proxy(nginx-proxy-manager),backup-job- Optional:
insights-sidecar,analytics-db,llm-gateway
Identifiers and casing
- snake_case for analytics DB tables; kebab-case for service names; camelCase for JSON payloads
Suggested artifacts (optional add-ons)
insights.recurring_items,insights.anomalies,insights.monthly_rollups,insights.merchant_aliases