All case studies

SaaS · Scaling

Payment API for 6 million users.
Stabilized, scaled, delivered.

A grown payment infrastructure carrying too much technical debt. Legacy stabilized, new Go microservices built alongside it, both systems cleanly integrated, without interrupting live payments.

Book a call
VPN SaaS payment infrastructure
6M+users
–15%payment drop-offs
–75%deployment time

The starting point

A system that had stopped scaling.

An international SaaS product with several million customers ran a payment API that had originally been built for a different order of magnitude. The system worked, but every load spike was a risk. New payment provider integrations took weeks. The codebase had grown, the dependencies were opaque, and deployment was a manual process that cost nerves.

At the same time the product was meant to scale internationally. New markets, new payment providers, new requirements. The existing system had not been built for that.

On top of that comes a trait that sets payment systems apart from most other backends: a bug here is never just a bug. A request executed twice is a customer charged twice. A timeout at the wrong moment can mean money moved while your own system knows nothing about it. And none of those situations end up in an error log. They end up with customer support.

The challenge

Modernization while it keeps running.

A full rewrite was not an option. The system processed thousands of transactions a day, an outage would have meant direct lost revenue. At the same time the architecture had to be modernized from the ground up to hit the scaling targets.

So the challenge was not only technical but also organizational: modernization without interrupting operations, new functionality alongside the stable old system, and all of that over several years without destabilizing anything.

The actual core

Why nine payment providers and not one.

From the outside it looks like complexity you could save yourself. In practice it is the precondition for taking money internationally at all. No single provider covers every market, and in many countries the payment method decides whether a purchase happens: cards do not work everywhere, direct debit is regional, and a noticeable share of customers only pay with what they already know.

The second reason is resilience. A payment provider is a third party system whose availability you do not control. With only one, you sell nothing while it has an incident. With several, you can route around it, provided the architecture allows for it.

The price is nine different interfaces, nine data models, nine ways of reporting a failure, and nine statements that have to match your own numbers at the end of the month. That is exactly why each provider got its own service behind one shared internal interface: the peculiarities stay where they belong, and the rest of the system only knows about a payment.

My approach

Stabilize.
Build in parallel.
Integrate cleanly.

01

Stabilize the legacy backend

Test coverage introduced, critical dependencies documented, deployment automated. Only once a system runs stably can you sensibly develop it further.

02

Microservice architecture in Go

Not as a one-shot replacement, but step by step. New services in Go, existing PHP components integrated over gRPC. Kubernetes on AWS for orchestration, CI/CD pipelines with GitHub and GitLab for automated deployments.

03

Payment provider integration

Stripe, Braintree, Adyen, Paymentwall, Chargebee and Amazon Pay abstracted behind clean API layers. Every provider its own service, replaceable without touching the system as a whole.

04

Repeatable, without charging twice

Every payment carries a key that identifies the business transaction, not the individual attempt. That makes a request safe to repeat after a timeout: the second call returns the result of the first instead of moving money again. Whatever still does not go through lands in a queue of its own with clear ownership, rather than nowhere.

05

Observability from day one

Grafana, Prometheus, CloudWatch and Sentry for monitoring, so problems become visible before they turn into outages. With payments what counts is not the technical error rate but the business one: how many started payments actually complete. A provider can answer with HTTP 200 and decline payments by the dozen.

Does your system sound familiar?

Let us find out in 30 minutes whether I can help.

Book a call

What was hard

The parts you do not see in advance.

Reconciliation instead of assumption. The most demanding part was not triggering payments but answering whether your own system and the provider statement say the same thing at the end of the month. Payments stuck in an intermediate state, chargebacks, refunds, currency differences: each case is unremarkable on its own, together they decide whether you can trust your own numbers.

Testing against other people's systems. Provider sandboxes do not behave like their production systems. Some failure cases cannot be triggered there at all, and those are precisely the interesting ones. Whatever could not be reproduced had to be handled in our own system without ever having seen it happen.

Two systems, one truth. Throughout the rebuild the legacy system and the new services ran side by side. The hardest decision was the same one every time: which of the two is right in a given case. Answering that per data area up front, instead of debating it during an incident, was in hindsight the most valuable preparation.

The outcome

Stable. Scalable. Ready for new markets.

6M+

users

The system carries the full load today, stably and reliably.

–15%

payment drop-offs

Through a stabilized and optimized payment infrastructure.

–75%

deployment time

Through fully automated and optimized CI/CD pipelines.

A sustainably scalable, highly available payment infrastructure that makes fast international growth possible. The system runs stably, new payment providers can be integrated in days instead of weeks, and the development team can make changes without fearing unknown side effects.

Technologies used

Proven tools. No experiment.

Backend
  • Go
  • gRPC
  • Laravel
  • PHP
  • Zend Framework
  • Phalcon
  • REST
  • Microservices
Infrastructure
  • AWS EC2
  • RDS
  • SQS
  • SNS
  • Lambda
  • Kubernetes
  • Terraform
  • Docker
  • GitHub Actions
  • GitLab CI
Observability
  • Grafana
  • Prometheus
  • CloudWatch
  • Sentry
Payment
  • Stripe
  • Braintree
  • Adyen
  • Paymentwall
  • Chargebee
  • Amazon Pay

Client voices

What clients say.

“Mr Rutte built a fully custom CRM for us, tailored exactly to our needs. Working together was straightforward. He implemented our requirements perfectly and the system runs absolutely stable.”

Stefan SchubertClient · Trustpilot, October 2025, translated from German

“Tim worked with us as a PHP developer and did a really good job. He got up to speed on the project quickly and always found a solution, even on tricky topics. The code was clean, easy to follow and genuinely moved us forward. We would work with Tim again any time.”

Anonymous reviewClient · ProvenExpert, September 2025, translated from German

“The development of our software was completed as agreed and all problems were resolved. Many thanks.”

Anonymous reviewClient · ProvenExpert, February 2026, translated from German

Frequently asked

What clients ask before deciding.

Did payments keep running during the rebuild?

Yes, without interruption. The existing backend was stabilized first, the new Go services ran alongside and were connected over gRPC. Traffic was redirected step by step rather than switched on a date.

How were payment drop-offs reduced by 15 percent?

Through three things: retries were made idempotent so an aborted attempt could not double-charge; timeouts against the payment providers were set realistically; and failure cases got a fallback path instead of an error message.

How many people were involved?

An existing team plus me. My role was architecture and implementation at the critical points, plus the handover: pairing, runbooks and documented decisions, so the team continues without me.