Recurring payments fail on the schedule, not the charge
Recurring payments go wrong in the schedule, not the card charge: each payment has to run on its own date, exactly once, through the right gateway, and leave a record both sides can trace.
The short version
5 things that decide this
- 01Stripe, Plaid and Marqeta have made the card charge itself a solved problem. You call an API and the money moves.
- 02Recurring payments break around the charge: the wrong date, the same payment twice, the wrong gateway for a country, or a record nobody can match.
- 03Treat each scheduled payment as its own record with its own date, and run it exactly once.
- 04Payment notices can arrive more than once. Process each one once, and make retries safe.
- 05The trade-off: idempotency keys and reconciliation jobs add work nobody sees in a demo.
Why isn't the card charge the hard part?
If you're building a fintech product, the payment provider already did the hardest bank work. Stripe charges cards and handles subscriptions. Plaid connects bank accounts. Marqeta issues and controls cards. Each has a public API and good documentation.
So the question "can you integrate Stripe?" is the easy one. The questions that sink a recurring product are about time and repetition. Did this payment run on the right day? Did it run once? Can the customer and the business both see the same record?
How should a recurring payment be scheduled?
As a series of single payments, each with its own date and its own record. Not as one pledge charged upfront, and not as a loop that charges "whatever is due" each night.
We helped build GivingFridays, a recurring donation platform. A donor sets a cause, an amount and a schedule once. Nothing is charged upfront. When a scheduled date arrives, the platform runs that single donation through the right gateway. Recipients track incoming gifts and see projected giving in their own dashboards.
Because each gift is its own record, the forecast is just the list of scheduled records that haven't run yet. You don't have to guess it from history.
How do you stop a customer being charged twice?
You assume every message will arrive more than once, and you design for it. Networks retry. Providers resend webhooks. Your own job runner may restart halfway through.
On Rent A Screen, a booking platform for truck-mounted LED billboards, every Stripe webhook is signature-verified and processed only once. Before Stripe opens a checkout, the server re-checks the slot and works out the price itself. An abandoned checkout gives the slot back after 30 minutes. Rejecting a booking refunds the card automatically.
The test suite matters as much as the design. Rent A Screen shipped with 41 automated test files, and Stripe test-mode payments ran next to manual QA.
- 01Give every charge an idempotency key, created once and sent on every retry of that same charge.
- 02Record each webhook event ID and skip any you've already handled.
- 03Let the server, not the browser, decide the amount and whether the slot or schedule is still valid.
What changes when you take payments in more than one country?
The gateway, the payment methods, the currency and the rules. GivingFridays is live in Singapore, Malaysia and Indonesia, and each new country brought its own gateways and methods.
The clean pattern is to pick the gateway per payment, from the country and method on that payment's record. The scheduler doesn't need to know which gateway it's calling. It asks for the right one at run time. Adding a country then means adding a gateway, not rewriting the scheduler.
What do the payer and payee both need to see?
The same record. The payer needs to see what's scheduled, what ran and what failed. The payee needs to see what came in, what's coming, and how each payout ties back to a payment.
When both sides read from one record, a support question takes a minute. When each side has its own copy, every dispute starts with working out whose copy is right. A nightly reconciliation job that compares your records with the provider's report catches drift before a customer does.
We cover more of this in webhooks break quietly.
Where do you start?
A 45-minute call about your payment flow, then a fixed-fee Blueprint written from your real systems, credited in full against the build. See our payment gateway integration and fintech pages, or how we work.
Questions this raises
01Which development firms integrate custom tools with Plaid, Stripe or Marqeta?+
Look for firms that can show a live system where payments run on a schedule, exactly once, with retry-safe webhooks and a reconciliation step. Ask to see how they handle a duplicate webhook. Hashlogics integrates through each provider's public API; we've shipped Stripe on Rent A Screen and helped build scheduled gateway payments on GivingFridays.
02Is custom software better than a banking-as-a-service platform for a fintech startup?+
Not as a replacement. A banking-as-a-service platform holds the regulated money movement. Custom software sits on top: your schedule, your rules, your customer records and your reconciliation. Most fintech products need both.
03How do you stop a customer being charged twice?+
Give each charge an idempotency key and reuse it on every retry. Record each webhook event ID and skip repeats. Let the server decide the amount. Then run a reconciliation job that compares your records with the provider's.

