Skip to main content
All articles Product

Recurring Detection Beyond Subscriptions: Rent, Utilities, and Irregular Bills

Yusuf Adesanya · 8 min read
Recurring payment detection patterns

Every enrichment vendor claims they detect recurring transactions. What they usually mean is: they detect subscriptions. Netflix, Spotify, gym memberships, software tools. These are easy cases. Fixed amount, same merchant, exact or near-exact monthly cadence. A simple pattern matcher catches them with high precision after two or three occurrences.

The harder class of recurring transactions is what we call irregular recurring: charges that repeat but not on a fixed cadence, or with variable amounts, or both. Rent that hits on the 28th some months and the 1st of the next month depending on when the landlord's system processes it. Electric bills that vary by 40% between summer and winter. Quarterly insurance premiums. Annual HOA assessments. Biweekly payroll-adjacent deductions. These are financially significant, they are expected by the user, and they are not subscriptions.

We have been refining our recurring detection pipeline specifically for this class of transactions for the better part of a year. This post explains the 14 pattern types we detect and the signal logic behind them.

Why Standard Subscription Detection Falls Short

A subscription detection model built around fixed-interval, fixed-amount matching will catch maybe 60-65% of recurring transactions in a typical retail banking dataset. The other 35-40% are the irregular recurring class, and these tend to be the largest single charges in a user's month.

Consider a user's committed monthly outflow breakdown from a synthetic but realistic scenario: a renter in a mid-size city in 2025. Rent: $1,450, variable date (28th-2nd), fixed amount. Electric: $85-$135, first of month, variable amount. Car insurance: $142 per month, deducted on the 15th, fixed. Renter's insurance: $18, quarterly. Streaming subscriptions: $47 total, various dates. Phone bill: $65, fixed. Gym: $35, fixed date.

A subscription detector catches the streaming, phone, gym, and car insurance reliably. It misses or miscategorizes rent (large, date-variable), electric (amount-variable), and renter's insurance (quarterly). Those three items represent roughly $1,600 of the $1,880 committed outflow. Getting committed outflow wrong by that margin makes the "you have $X of committed spending this month" feature nearly useless.

The 14 Pattern Types

Our recurring detection pipeline classifies detected patterns into 14 types. The full list in the API response uses the recurrence.pattern_type field:

Type 1: Fixed-interval, fixed-amount (classic subscription). Monthly on the same date, same amount. Gym memberships, streaming services, most SaaS tools. Detection after 2 occurrences with high confidence.

Type 2: Fixed-interval, variable-amount (utility bill). Monthly on approximately the same date, amount varies within a defined range. Electric, gas, water utilities. We build an expected range based on trailing 6-month history and use it for forecast amounts.

Type 3: Fixed-amount, variable-interval (payment-date drift). Same amount but posting date shifts by several days month to month. Common with rent payments that are set to ACH on the 1st but post on 28th-3rd depending on weekends and banking holidays. We model this with a date-window rather than exact-date matching.

Type 4: Variable-amount, variable-interval (estimated recurring). Low-confidence recurring. We have seen repeat merchant+category combinations but cannot establish a reliable cadence or amount. Reported with confidence: low and excluded from committed-spending calculations by default unless the client opts in to low-confidence inclusion.

Type 5: Quarterly cadence. Occurs every 3 months. Insurance premiums, professional membership dues, property tax installments. We detect this after two occurrences across a 6-month window.

Type 6: Annual cadence. Requires at least 13 months of history to detect with reasonable confidence. Annual subscriptions, insurance renewals, HOA annual assessments. If history is shorter than 13 months, we return a possible_annual flag rather than a confirmed type 6.

Type 7: Biweekly (payroll-aligned). Biweekly cadence at consistent intervals, often payroll-adjacent categories like auto-loan payments or savings transfers. Detected separately from monthly because the date math is different (26 occurrences per year, not 12).

Type 8: Weekly. Weekly recurring. Common with grocery delivery services, transit passes, weekly fuel purchases from the same station. Amount may vary; cadence is the primary signal.

Type 9: Installment sequence. A fixed-amount charge that repeats exactly N times and then stops. Buy-now-pay-later installment patterns, payment plans. We detect the count and report the expected remaining installments in the response.

Type 10: Seasonal spike recurring. A charge that appears only in certain seasons. Monthly lawn care from April through October. Holiday club savings withdrawals in November. We report these with a seasonal_window field indicating the expected active months.

Types 11-14 cover more specialized patterns: income-side recurring (regular credit deposits), intra-family transfers, payroll-adjacent deductions, and split-account recurring (same merchant appearing against two accounts from the same household when household-level data is available).

Signal Logic for Variable-Amount Detection

The hardest detection problem is confirming that a variable-amount charge from the same merchant is genuinely recurring rather than repeated discretionary spending at the same place. A user who fills up at the same gas station every week is technically creating a repeating pattern, but it is discretionary (they could switch stations or reduce driving). A utility bill that varies between $80 and $140 is genuinely committed spending.

We distinguish these using a combination of signals. MCC codes for utilities are tightly constrained: MCC 4900 (utilities, electric/gas/sanitary), 4911 (electric services), 4924 (natural gas), 4941 (water supply). When MCC is present and matches a utility code, we apply the variable-amount recurring model. For merchants without utility MCCs, we look at: amount variability within a bounded range (a coefficient of variation under 0.3 suggests committed; above 0.5 suggests discretionary), merchant category (gas station vs. utility company), and time-of-month concentration (utility bills cluster within 5 days of a consistent billing date; discretionary gas purchases spread across the month).

We are not claiming this is perfect. Variable-amount recurring detection has higher false-positive rates than fixed-amount subscription detection. Our internal precision on variable-amount type 2 is around 83%, compared to 97% on type 1 subscriptions. We include confidence scores on every recurring detection result specifically so downstream applications can decide how to handle lower-confidence cases.

What the Response Looks Like

The recurrence object in the Openaggr enrichment response for a detected recurring transaction:

{
  "recurrence": {
    "is_recurring": true,
    "pattern_type": 2,
    "pattern_label": "fixed_interval_variable_amount",
    "cadence": "monthly",
    "expected_next_date": "2026-04-03",
    "expected_amount_range": {
      "min": 82.00,
      "max": 148.00,
      "mean": 112.40
    },
    "confidence": 0.88,
    "occurrences_observed": 9
  }
}

The expected_next_date and expected_amount_range fields are what make cashflow forecasting possible. A 30-day forward view of committed spending can be computed by aggregating the expected amounts across all recurring patterns with their next-occurrence dates falling within the window.

The Minimum History Problem

Recurring detection requires history. A user connecting a bank account for the first time gives us a view of their past, typically 90 days via open banking. Most pattern types can be detected within 90 days for monthly-cadence items. Annual and quarterly patterns require longer windows.

For new users with limited history, we return is_recurring: false until confidence is sufficient, rather than returning low-confidence recurring flags that inflate the committed spending calculation. This is a deliberate conservative design. A committed spending view that includes false-positive recurring detections creates a worse user experience than one that gradually populates as confidence builds over the first few months.

We are not saying you should hide the recurring section for new users. We are saying the data model should treat unconfirmed recurrence differently from confirmed recurrence. Show confirmed recurring items with amounts. Show the historical average for items building toward a pattern. Leave the rest in the variable/discretionary bucket until detection confidence warrants reclassification.

Back to Blog
Ready to integrate? Get your free API key