Where Should a Payment Gateway End? Drawing the Line Between Payments, Billing, and Orders
Key Takeaways
- •The proposed architecture defines four logical ownership boundaries—the payment gateway, the payment service, billing, and orders—which can start as modules within a single application rather than four separate microservices.
- •The gateway should handle only provider-facing tasks such as translation, authentication, and notification verification, and should contain no product knowledge like loyalty tiers or subscription grace periods.
- •The payment service must maintain a state model that accommodates unresolved outcomes, since timeouts, late notifications, and out-of-order updates are routine, and a timeout should never automatically trigger a new charge.
- •Billing owns financial obligations and must issue every collection request with an explicit amount, currency, and obligation reference, while the order domain decides fulfillment conditions and cancellation policies.
- •Teams should test the boundaries by walking through business changes—such as adding a payment provider or altering fulfillment policy—and by structuring refund workflows so that approval, calculation, execution, and recording remain under distinct owners.

Consider a checkout in which the payment succeeds but the order update fails. The customer sees an error and tries again. In the meantime, support holds a transaction record, the warehouse has no confirmed order, and finance needs to know whether the customer owes anything.
Which system should resolve the situation? Incidents like this are where architecture decisions become visible: when ownership is undefined, each occurrence gets a hand-built fix, and those fixes tend to accumulate wherever they are easiest to write.
An architecture should answer that question before the first transaction reaches production. Otherwise, payment code gradually absorbs order recovery, subscription rules, invoice adjustments, and fulfillment decisions.
The ownership model outlined below offers a practical starting point: keep the gateway focused on provider communication, give payment operations a home of their own, and leave decisions with billing and orders.
Start With Four Responsibilities, Not Three
For this design, distinguish the payment gateway from the broader payment service. The model uses four logical boundaries covering the gateway, the payment service, billing, and orders.
Treat these as ownership boundaries rather than an instruction to deploy four microservices. Starting with modules inside one application is fine if that suits the team. Either way, the responsibilities should be made explicit.
When reviewing payment gateway architecture, pair the component diagram with a decision map: who decides the amount, who requests collection, who records the outcome, and who authorizes the next business action?
Keep the Gateway Close to the Provider
Give the gateway a narrow contract. It should accept a supported payment operation, translate it into the provider's format, and return a result the payment service can interpret.
The isolation has a practical motivation: payment providers differ in APIs, authentication schemes, field formats, and notification mechanisms, and consolidating that variation in one layer keeps the rest of the system insulated from provider specifics.
Assign it responsibilities such as:
- Validating the provider-facing request
- Authenticating communication with the provider
- Translating internal fields into provider-specific fields
- Verifying incoming provider notifications
- Mapping responses while retaining useful provider details
Product knowledge stays out of that contract. The gateway should not need to understand loyalty tiers, shipping eligibility, subscription grace periods, or promotional bundles. Pass it the approved amount, currency, payment reference, and required payment-method information—not the rules that produced them.
A useful review question: would changing the return policy require changing gateway code? If so, reconsider the boundary.
Give Payment Operations a Separate Owner
Payment attempts and their outcomes belong in the payment service. For each attempt, record an internal identifier, relevant provider references, requested amount, currency, operation type, and state. Preserve enough history to investigate what was requested and what was actually confirmed.
Avoid reducing the model to a single paid flag. Define the distinctions the workflows need instead, including unresolved outcomes. Provider communication is genuinely uncertain at times—timeouts, late notifications, and out-of-order updates are routine—so the state model needs room for ambiguity rather than collapsing every outcome into success or failure.
Design explicitly for this hypothetical sequence: the payment service requests an authorization, the request reaches the provider, and the response is lost. The application must then decide what to do next. A timeout should never automatically trigger a new charge. Require the payment service to resolve or safely manage the original attempt before another operation is allowed.
Two kinds of retry should also be separated:
- Technical retry: repeating communication for the same intended operation under defined safety rules.
- Collection retry: making a new attempt to collect an outstanding balance.
Assign technical retry handling to the payment integration design. Billing determines collection timing and eligibility, with the payment service executing the approved attempt.
Let Billing Decide What Is Owed
Billing owns the financial obligation: the charge calculation, the invoice, credits, and the remaining balance. For a subscription product, rules for plan changes, prorations, billing periods, and collection schedules belong here.
Require billing to issue every collection request with an explicit amount, currency, and reference to the obligation being collected. The payment service reports the outcome, and billing then determines how that outcome affects the balance.
Consider a hypothetical $100 invoice carrying a30 credit. Billing should request the remaining $70. The gateway should never be asked to reconstruct that calculation from subscription metadata.
The stakes grow with pricing complexity: every calculation that lands in the wrong component becomes logic that must later be found, migrated, and reconciled across systems.
The same discipline applies after a refund. Payment records establish what was returned through the provider; billing determines which invoice or balance adjustment corresponds to that return.
Let Orders Decide What Happens to the Purchase
Fulfillment and purchase lifecycle decisions stay with the order domain. The payment service should publish a payment outcome, not issue a warehouse instruction, and the order workflow should interpret that outcome alongside its other requirements. Interpreting the outcome is a business judgment as much as a technical one, since the same confirmed payment can carry different weight for different fulfillment models.
One example of an explicit fulfillment rule: release the order only when the required payment condition is satisfied, inventory is allocated, and any required review is complete. The payment condition should be chosen to fit the business model and never buried inside a provider response handler.
Cancellations deserve the same separation. Orders decide whether cancellation is permitted and what should happen to the purchase, then request the appropriate payment operation through the payment service. Avoid an overloaded “cancel” command that might mean cancel the order, release an authorization, refund a payment, or terminate a subscription. Name each action precisely.
Coordinate Refunds Without Giving One System Every Job
A refund workflow is a good test of whether the boundaries hold. Suppose a customer returns one item from a three-item order. Structure the workflow so that:
- The returns or order component approves the return.
- The designated commercial calculation owner determines the refundable amount.
- The payment service checks the payment history and applicable operation limits.
- The gateway submits the provider request.
- The payment service records the confirmed or unresolved outcome.
- Billing and orders update their own records accordingly.
Assign one owner to each calculation. Billing and orders should not independently calculate different refund amounts and leave payments to choose between them.
Keep “refund requested” separate from “refund confirmed.” If the provider result is unresolved, retain that uncertainty and provide an investigation path rather than marking the entire workflow complete.
Make Recovery Part of the Contract
Every cross-boundary operation should specify more than the successful response. Document:
- How repeated requests are identified
- Which component owns the authoritative state
- How late or duplicate notifications are handled
- What happens when the next component is unavailable
- How staff investigate unresolved outcomes
- Which actions can be retried safely
For repeated requests in particular, providers commonly offer idempotency mechanisms designed for exactly this purpose, allowing the same operation to be resubmitted without being executed twice.
Give each domain its own identifiers and connect them explicitly: order ID, invoice ID, payment ID, attempt ID, and provider reference. Do not force one identifier to represent every relationship.
Support staff can receive a combined timeline, but corrections should remain under the owning component's controls. A convenient dashboard should not become permission to overwrite payment history or silently alter invoice balances.
Test the Boundaries With Business Changes
Before approving the design, walk through several changes:
- Add a payment provider without changing pricing rules.
- Change subscription collection timing without editing gateway adapters.
- Introduce partial returns without rewriting provider notification handling.
- Change fulfillment policy without altering payment state definitions.
Treat unexpected cross-component changes as review signals. Some coordination is legitimate; unexplained coupling deserves attention.
Ownership drift rarely announces itself; it accumulates one expedient change at a time. Rerunning these walkthroughs whenever a new provider, payment method, or pricing model is introduced keeps the boundaries explicit long after the initial design review.
The gateway should end at provider-facing payment communication. The payment service should own payment execution and evidence. Billing should own obligations and balances. Orders should own the purchase and its fulfillment.
Write those responsibilities into interfaces, recovery procedures, and team ownership. A diagram alone will not keep them separate.