FR

Commerce Systems

Reference Architecture

Transaction & Commerce Integration Architecture

Reference architecture for connecting commerce-oriented applications with payments, identity, and transactional backend systems.

Node.jsPythonPostgreSQLStripeOAuthREST APIsWebhooks

Retry-Safe

Payment handling under retries

Verified

Webhook signature validation

Audit Trail

Transaction state history

Client
Application API
Transaction ServiceOwns transaction state
Coordinates with
PostgreSQL
Payment Providere.g. Stripe
Identity ProviderOAuth
Webhook Processing
Analytics / External Services
01

Project Summary

A representative reference architecture, generalized from independent/freelance work integrating payment and identity providers into transaction-oriented backend systems. This is a reference pattern — it is not presented as a specific employer engagement, and no employer-specific business details are implied.

02

Business / Engineering Problem

Commerce-oriented applications need to coordinate a synchronous checkout flow with an asynchronous, provider-driven confirmation (a webhook) — while guarding against duplicate charges, spoofed events, and inconsistent state if any step fails partway through.

03

Requirements

  • Process payments without risk of double-charging a customer on retry.
  • Trust inbound webhook events only after verifying they actually came from the provider.
  • Keep a complete, auditable record of every transaction state transition.
  • Coordinate payment, identity, and analytics systems without tightly coupling the application to any single provider's API shape.
04

Constraints

  • Payment and identity providers control their own retry and webhook delivery semantics — the architecture has to assume duplicate and out-of-order delivery, not prevent it.
  • Sensitive payment data should touch as little of the application as possible, favoring provider-hosted fields over handling raw card data directly.
  • Checkout UX expects a fast synchronous response, while final payment confirmation often arrives later via webhook.
05

Architecture

The client calls an application API, which delegates to a transaction service responsible for owning transaction state end-to-end. The transaction service writes to PostgreSQL as the system of record, initiates calls to the payment provider (e.g. Stripe) and identity provider (OAuth), and separately ingests asynchronous webhook events. Webhook processing is decoupled from the synchronous checkout path so a slow or duplicate provider callback never blocks or corrupts the user-facing request. Downstream analytics and external services read from the transaction service's confirmed state rather than participating in the checkout path directly.

06

Data Flow

A client-initiated checkout hits the application API, which asks the transaction service to create a pending transaction record and initiate a charge with the payment provider. The provider later delivers a webhook confirming (or rejecting) the charge. The webhook handler verifies the provider's signature, checks the event against an idempotency key before applying it, and updates the transaction record accordingly. Only a verified, deduplicated event is allowed to transition transaction state.

07

Technical Decisions

Enforce idempotency keys on every mutating payment endpoint, backed by a database unique constraint.

Application-level idempotency checks (e.g. an in-memory or cache-based check) can race under concurrent retries. A unique constraint at the database layer is the only guarantee that survives concurrent duplicate requests.

Verify webhook signatures before trusting any inbound payload.

An unauthenticated webhook endpoint is a direct path for an attacker to spoof a 'payment succeeded' event. Signature verification is treated as non-negotiable, not an optional hardening step.

Separate webhook ingestion from transaction-state mutation.

Providers retry webhooks aggressively on anything but a fast 2xx response. Acknowledging receipt immediately and processing the event's effect separately avoids provider-side retry storms and keeps the webhook endpoint fast and simple.

08

Alternatives Considered

Trust webhook payloads without signature verification

Accept and act on webhook events based on payload shape alone.

Why not: Leaves the transaction system open to spoofed events from anyone who can guess or discover the webhook URL — an unacceptable risk for anything touching payment state.

Process webhooks synchronously inline with the request handler

Apply the transaction-state change directly inside the webhook HTTP handler before responding.

Why not: Ties response latency (and the provider's retry behavior) to however long state mutation and any downstream side effects take, increasing the chance of a provider-side timeout triggering a duplicate retry.

09

Tradeoffs

Eventual consistency between checkout and confirmation

The application may briefly show a transaction as pending after checkout, until the provider's webhook confirms it — an intentional tradeoff for not blocking the user on a provider round-trip.

Added complexity from idempotency and dedup logic

Idempotency keys and webhook deduplication are extra moving parts, justified entirely by the cost of a duplicate charge or a corrupted transaction record.

10

Reliability

Idempotent write paths and webhook deduplication mean provider retries — expected, routine behavior — never produce duplicate charges or conflicting state. Failed reconciliation is surfaced for inspection rather than silently dropped.

11

Performance

Decoupling webhook acknowledgment from state processing keeps the webhook endpoint's response time low and predictable, which in turn keeps provider retry behavior calm rather than compounding under load.

12

Security

Payment data exposure is minimized by relying on the provider's hosted fields rather than handling raw card details. Identity is handled via OAuth against a trusted provider, and every inbound webhook is signature-verified before it can affect transaction state.

13

Infrastructure

The application API and transaction service are stateless and horizontally scalable, backed by PostgreSQL as the durable system of record for transaction history.

14

Observability

Every transaction-state transition is logged, and signature-verification failures or reconciliation mismatches between the checkout flow and webhook confirmation are treated as alertable events, not just log noise.

15

Results

  • Idempotent payment handling eliminates duplicate charges under provider retries.
  • Signature verification blocks spoofed or malformed webhook payloads before they can affect transaction state.
  • Clear separation between the synchronous checkout flow and asynchronous confirmation simplifies reasoning about partial failures.
16

Lessons Learned

  • Idempotency has to be enforced at the database layer via a unique constraint — application-level checks alone don't survive concurrent retries.
  • Webhook endpoints should be designed assuming duplicate and out-of-order delivery from day one, not patched to handle it after the first incident.
  • Minimizing what the application touches directly (raw card data, in this case) reduces both security surface and compliance scope.

Interested in how this would apply to your system?

I'm open to senior backend, platform, and full-stack roles, and select consulting engagements.