Stoke Money's Cash Flow Forecast Engine: How Real-Time Financial Projections Replace Static Budget Categories
Stoke Money replaces the category-based budget with a forward-looking cash flow forecast. Instead of tracking how much you spent on groceries this month, it projects your checking account balance 30 days out, updating the line every time a transaction arrives. The product surfaces a single question: will rent clear on Friday? This shifts the engineering problem from retrospective categorization to predictive modeling. You need pattern detection that distinguishes recurring bills from one-time purchases, a data structure that represents confidence intervals for future transactions, and a recalculation strategy that keeps forecasts fresh without thrashing on every $5 coffee purchase. Architecture: Ledger as Forecast Input Stoke merges historical transactions and projected events into a single timeline. The ledger is not just a log of what happened. It is the input to a projection engine that extends each account balance forward, day by day. Core components: Transaction ingestion: Plaid-style bank sync or manual entry. Both feed the same pipeline. Recurring pattern detector: Scans transaction history for repeating amounts, dates, and counterparties. Groups paychecks, rent, subscriptions. Projection engine: Takes detected patterns and generates future transaction stubs with confidence scores. Balance calculator: Walks the merged timeline (historical + projected) to produce a daily balance curve. User override layer: Lets you adjust projected amounts or dates. Changes propagate through the forecast immediately. The key difference from Mint or YNAB: cash leaves your forecast when the credit card payment clears, not when you swipe. This matches actual liquidity timing. Recurring Pattern Detection Without Manual Tagging Traditional budgeting apps ask you to categorize every transaction. Stoke flips this: it infers recurring patterns from raw transaction data, then asks you to confirm or correct only the ambiguous cases. Detection heuristics: Amount clustering: Transactions with the same counterparty and similar amounts (within 5%) over multiple months get flagged as recurring. Date interval analysis: If a transaction repeats every 28-31 days, it is likely monthly. Every 14 days suggests biweekly payroll. Counterparty fingerprinting: Normalize merchant names (e.g., "AMZN MKTP" and "Amazon Marketplace" collapse to one entity). Confidence scoring: Patterns with three or more historical instances score higher. One-off transactions stay in the "unclassified" pool. When a new transaction arrives, the system checks if it matches an existing pattern. If yes, it updates the pattern's next projected occurrence. If no, it evaluates whether this transaction starts a new pattern (e.g., a new subscription). User correction loop: Misclassified transactions get a "not recurring" flag. Missed patterns get a "create rule" action that applies retroactively and forward. Rules are stored as simple predicates: if counterparty contains "Spotify" then category = "Subscriptions", recurring = true. Forecast Data Structure and Recalculation Triggers The forecast is a time-series of projected balances, not a static budget. Each account gets its own projection curve, and the system recalculates whenever new data arrives. Data model: interface ProjectedTransaction { id: string; accountId: string; date: Date; amount: number; counterparty: string; category: string; confidence: number; // 0.0 to 1.0 isHistorical: boolean; patternId?: string; // links to recurring pattern } interface ForecastCurve { accountId: string; startDate: Date; endDate: Date; dailyBalances: Array; } Recalculation strategy: Incremental updates: New transactions trigger a recalc only for the affected account and dates >= transaction date. Batch mode: Overnight job recalculates all accounts to catch pattern drift (e.g., a subscription that increased in price). User-initiated refresh: Manual sync button forces a full recalc across all accounts. The system avoids recalculating the entire forecast on every $5 coffee purchase by maintaining a dirty flag per account. Only accounts with new transactions since the last recalc get reprocessed. Confidence Intervals and Sparse Data Handling Not all projected transactions have the same certainty. Payroll is predictable. A quarterly tax payment might vary by thousands of dollars. Confidence scoring: Pattern Type Confidence Reasoning Biweekly payroll 0.95 Fixed amount, fixed schedule Monthly rent 0.90 Fixed amount, slight date variance Utility bill 0.70 Variable amount, predictable timing Quarterly tax 0.50 Variable amount, infrequent history One-time purchase 0.10 No pattern, user must confirm The forecast curve includes low and high confidence bounds. If your checking account balance is projected at $3,450 on November 11, the bounds might be $3,200 to $3,700 depending on whether that utility bill comes in at $150 or $200. Sparse data fallback: If a pattern has fewer than three historical instances, the system flags it as "needs confirmation." Seasonal patterns (e.g., holiday spending) require at least one full year of data. Otherwise, the forecast omits them or uses a generic average. New accounts start with zero projected transactions until the first sync populates history. External Account Sync and Stale Forecast Mitigation Stoke relies on Plaid or similar aggregators for bank sync. API latency and rate limits create staleness risk: your forecast might show $3,450, but the real balance is $3,200 because a transaction posted but has not synced yet. Sync architecture: Polling interval: Accounts sync every 4 hours during business hours, every 12 hours overnight. Webhook support: If the aggregator supports webhooks (e.g., Plaid's transaction updates), Stoke triggers an immediate recalc. Staleness indicator: If the last sync is more than 24 hours old, the UI shows a warning and disables high-confidence projections. Manual sync escape hatch: Users can force a sync, but rate limits may block it. The system queues the request and retries. Failure modes: Aggregator downtime: Forecast continues using the last known state but flags all projections as "unverified." Credential expiration: User must re-authenticate. Forecast pauses until credentials are refreshed. Transaction deduplication: Aggregators sometimes send duplicate transactions. Stoke hashes (accountId, date, amount, counterparty) and drops duplicates. MCP Integration for AI-Assisted Categorization Stoke exposes an MCP server that lets Claude, ChatGPT, or other assistants query forecast data and perform categorization tasks. MCP tools: get_forecast(accountId, startDate, endDate): Returns projected balances and transactions. categorize_transaction(transactionId, category): Applies a category and creates a rule if the user confirms. create_recurring_pattern(transactionIds): Groups transactions into a new recurring pattern. adjust_projection(transactionId, newAmount, newDate): Overrides a projected transaction. Example workflow: User asks Claude: "Can I afford a $2,000 vacation in December?" Claude calls get_forecast("checking", "2026-12-01", "2026-12-31"). Claude sees the low confidence bound dips to $1,800 on December 15. Claude responds: "Your forecast shows a low point of $1,800 on December 15. If you book the vacation, you will need to move $200 from savings or delay the trip until after your December 20 paycheck." The MCP server runs as a sidecar process, authenticates via OAuth, and rate-limits tool calls to prevent runaway loops. Deployment Shape and Observability Stoke runs as a monolithic Rails app with background jobs for sync and recalculation. Infrastructure: Web tier: Heroku dynos or AWS ECS containers. Handles API requests and serves the React frontend. Background workers: Sidekiq processes poll the job queue for sync tasks and forecast recalcs. Database: PostgreSQL with time-series indexes on (accountId, date) for fast balance queries. Cache layer: Redis stores the most recent forecast curves to avoid recalculating on every page load. Observability: Forecast accuracy metric: Compare projected balances to actual balances 7, 14, and 30 days out. Track mean absolute error. Pattern detection rate: Percentage of transactions automatically classified vs. requiring user input. Sync latency: Time from transaction post to appearance in forecast. Recalc duration: P95 time to recalculate a single account's forecast. Alerts fire when forecast accuracy drops below 90% for accounts with more than three months of history, or when sync latency exceeds 6 hours. Likely Failure Modes Failure Impact Mitigation Aggregator API rate limit hit Sync pauses, forecast goes stale Queue requests, retry with exponential backoff Pattern detector misclassifies one-time purchase as recurring Forecast shows phantom future transaction User correction creates negative rule, recalc drops projection User changes bank account credentials Sync fails, forecast freezes Email alert, in-app banner, disable projections until re-auth Seasonal spending pattern with
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to