ChourioDev Logo
FinTech Featured

Migrating a SOAP Payment API to NestJS Microservices Without Downtime

How I migrated a high-volume SOAP payment API to NestJS microservices in production with zero downtime: bounded contexts, idempotency and the strangler fig.

Miguel Mendoza Chourio
10 min read Leer en español
Migrating a SOAP Payment API to NestJS Microservices Without Downtime
In this article

If you’ve worked in payments for a while, you know the scene: an API that takes tens of seconds when the business needs milliseconds. It’s not an edge case. It’s the kind of debt that stalls integrations, floods the support queue, and sends partners shopping for alternatives.

Working remotely from Caracas with international teams, I led exactly that migration at Andrómeda Ventures: from a SOAP monolith to microservices built on NestJS, PostgreSQL and Redis. The full case study is in my portfolio; this is the guide I wish I’d read before we started.

If you want the technical deep dive, with legacy code and detailed architecture, also read From 60 seconds to milliseconds: refactoring Andrómeda’s payment core.

1. Diagnosis: two weeks without writing a single microservice

Before designing anything, we mapped the critical flows:

  • Prepaid top-ups
  • Payment confirmation
  • Reconciliation with carriers
  • Partner notifications

For each one we measured p50, p95 and p99, not averages that hide the real pain.

Two findings changed the plan:

  1. ~80% of the time was spent on synchronous calls to external carriers.
  2. Unrelated domains were sharing tables and locks.

The takeaway: the problem wasn’t Node vs. Java. It was coupling.

2. Bounded contexts, not microservices for the sake of it

Splitting by layer (API / DB / queues) just moves the monolith somewhere else. We aligned services with the business:

DomainResponsibility
Top-upsPrepaid, carrier validation, reversals
PaymentsCharges, gateways, transaction states
ReconciliationMatching against external reports
NotificationsWebhooks, callbacks, retries

Rule of thumb: if two teams don’t evolve something independently, don’t split it yet. We ended up with four core services, not fourteen.

More on the architecture side in Backend architecture and microservices.

3. NestJS: a structure that holds up under payment load

We chose NestJS because the team already knew Node.js inside out and we needed explicit boundaries: modules, DI, guards, interceptors.

An API Gateway centralized auth, rate limiting and routing. The microservices don’t expose public endpoints directly.

PostgreSQL partitioned by carrier and date range. Indexes were designed around the reconciliation queries up front, not bolted on afterward.

Redis + BullMQ for anything that shouldn’t block the happy path: notifications, retries, deferred reconciliation.

Circuit breakers per external integration. When a carrier degrades, you cut traffic before it drags down your connection pool.

4. Idempotency: non-negotiable

In payments, a timeout without an idempotency key is a potential double charge. Design for it from the very first endpoint:

  • Idempotency keys per operation
  • Explicit transaction states
  • Retries with exponential backoff
  • End-to-end correlation IDs in the logs

5. Migrate without a big bang: the strangler fig

We didn’t switch off SOAP overnight. We routed traffic to the NestJS stack incrementally while the legacy system kept running for in-flight flows.

CI/CD with Docker and blue-green deployments for zero-downtime releases. Business-level observability from day one: TPS per domain, latency per integration, transactions pending for more than N minutes.

Results at Andrómeda Ventures

After the full migration:

  • From ~60 seconds to 150–300 ms on the critical path
  • 99.5% improvement in response time
  • 5,000+ transactions per hour (up from 50) and 99.8% uptime
  • Integrations with Stripe, Ingenico and Mercadopago without rewriting the core each time

Was it just the microservices? No. It was going async where it made sense, drawing clear domain boundaries, and no longer blindly trusting external integrations.

Five concrete lessons

  1. Don’t migrate out of dogma. Migrate when the monolith costs more than living with it.
  2. Idempotency from day one. Not after your first incident.
  3. A gateway with a purpose. Protect your public contracts and centralize cross-cutting concerns.
  4. Business metrics > pretty dashboards. TPS and pending states will alert you before support does.
  5. Remote work demands clarity. Working from Venezuela for clients in the US and Europe means documentation, small deliverables and flawless written communication.

Working on something similar?


About the author: Miguel Mendoza Chourio (Chourio DEV) is a senior FinTech engineer and software architect based in Venezuela, with 9+ years building payment systems and microservices for international remote teams. Connect on LinkedIn.

FAQ: FinTech migrations and hiring a remote FinTech engineer

Tags:

#soap-migration #nestjs #microservices #payment-systems #fintech #venezuela #nodejs #arquitectura-software
Miguel Mendoza Chourio

Miguel Mendoza Chourio

Miguel Mendoza Chourio (Chourio DEV) — senior FinTech engineer and software architect in Venezuela. 9+ years in high-volume payments, microservices and Enterprise AI. International remote.

Related articles

📧 Subscribe to the Blog

Get notified about new articles and exclusive technical content.

No spam. Unsubscribe anytime.