Payment Authorization on AWS: Credit Cards vs. Pix at Scale
Payment Authorization on AWS: Credit Cards vs. Pix at Scale
Series: Golden Jacket Field Notes (22 articles)
- …
- 7Payment Authorization on AWS: Credit Cards vs. Pix at Scale This article
Disclaimer
Originally published on Medium as Week 3 of Golden Jacket Field Notes**
Canonical URL: https://medium.com/aws-tip/architecting-payment-authorization-on-aws-credit-cards-vs-pix-at-scale-181d3129f829
This is a republication on AWS Builder Center for the AWS community. The piece below appeared first on Medium and is preserved here in its original form.
Golden Jacket Field Notes. Week 3.
How two fundamentally different payment models demand radically different cloud architectures
If you’ve ever swiped a card at a terminal or scanned a Pix QR code, you probably assumed the infrastructure behind both looked roughly the same. They don’t. Not even close.
I’ve spent nearly 10 years in cloud infrastructure with AWS. I’ve seen teams burn months trying to force-fit a card authorization architecture onto a Pix settlement flow. The result is always the same: latency blowouts, compliance gaps, and a system that barely survives its first Black Friday.
This article breaks down how to architect both payment models on AWS, from enterprise-grade systems handling hundreds of thousands of transactions per second down to lean startup stacks processing a few hundred per minute. The differences are not cosmetic. They’re structural, regulatory, and deeply technical.
The Fundamental Split: Pull vs. Push
Before touching any AWS service, you need to internalize the core difference.
Credit card authorization is pull-based. The merchant initiates the transaction. A customer taps their card, the acquirer sends a request upstream through the card network (Visa, Mastercard) to the issuing bank, which responds with an approval or denial. The merchant pulls money from the customer’s account.
The flow looks like this: Merchant → Acquirer → Card Network → Issuer → Response back down the chain.
Pix is push-based. The payer initiates the transaction. They open their banking app, scan a QR code or enter a key, and push money to the recipient. The recipient doesn’t request anything. They’re notified after the funds are already in transit.
This inversion changes everything: connectivity model, settlement timing, regulatory requirements, data store selection, and multi-region strategy. Let’s walk through each.
Credit Card Authorization: The Pull-Based Architecture
Enterprise Tier (50k–500k+ TPS)
At this scale, think about the big ones in the payment processing sector: Stone, Cielo, or any institution processing for an entire card network in a country. Every millisecond matters, and the SLA from card networks is typically around 300ms end-to-end, but internally you need to close your decision logic well under 50ms to leave room for network hops.
Ingestion layer: NLB, not ALB, not API Gateway.
The Network Load Balancer (NLB) operates at Layer 4, adding microseconds of latency, not milliseconds. An Application Load Balancer (ALB) parses HTTP headers, evaluates routing rules, and processes cookies at Layer 7. That overhead , TLS termination, header parsing, routing evaluation, and target group health checking combined , compounds fast when your entire latency budget is 50ms. In real-world benchmarks, the end-to-end difference between an NLB path and an ALB path ranges from a few milliseconds under light load to 20ms+ under production conditions with complex routing rules. When every millisecond is a business decision, that gap matters. API Gateway is even worse for this tier: it introduces throttling evaluation, request validation, and logging overhead on every single call, plus a default soft limit of 10,000 requests per second per account that wasn’t designed for this volume class.
Behind the NLB, EKS on EC2 with Karpenter, not Fargate. The reason is CPU control. Fargate abstracts away instance selection, CPU pinning, and NUMA topology. You can’t set cpuManagerPolicy: static on the kubelet, you can’t guarantee your decision pod is pinned to dedicated cores without kernel preemption, and you can’t select the exact instance type that you’ve benchmarked and validated for deterministic p99 latency. With Karpenter, you define NodePools constrained to specific instance families (like c7gn for Graviton with enhanced networking) and get dynamic, intelligent scaling without sacrificing hardware-level control.
A note on EKS Auto Mode: it simplifies operations significantly, but it optimizes for cost-efficiency when selecting instances. In an authorization engine, you don’t want “cost-efficient.” You want “the exact instance I tested and know delivers sub-10ms p99.” Reserve Auto Mode for the growth tier.
Decision engine: MemoryDB + DynamoDB, not one or the other.
This is where most architectures get it wrong by picking a single data store.
MemoryDB for Redis gives you sub-millisecond latency with durability. Unlike ElastiCache Redis, where a node failure can mean lost in-memory state, MemoryDB writes to a Multi-AZ transaction log. This means your real-time balance store survives node failures without data loss. Use Lua scripts for atomic conditional decrements (check balance, decrement, return result, all in one round-trip).
DynamoDB with DAX (DynamoDB Accelerator) serves as the durable ledger and rule store. DAX accelerates repeated reads (idempotency checks, account lookups, fraud rule retrieval) to single-digit microsecond latency from cache. But remember: DAX is read-only acceleration. Writes pass through DAX to DynamoDB without caching benefit. Don’t put DAX in the write path expecting speedup; it just adds a hop.
The combined pattern works like this: the request hits MemoryDB for the real-time balance check and atomic decrement, then writes asynchronously to DynamoDB as the durable ledger. If MemoryDB is unavailable, the system falls back to DynamoDB direct reads (degraded latency, but functional). MemoryDB becomes the fast source of truth for balance; DynamoDB becomes the audit and compliance ledger.
Redis (via MemoryDB) also handles aggregation patterns brilliantly. Need to know how many transactions this account executed in the last 60 seconds? That’s a sliding window counter with ZRANGEBYSCORE, resolved in microseconds. Doing that in DynamoDB would require query patterns that don’t scale gracefully under this load.
Anti-fraud: SageMaker real-time inference.
Deploy a custom ML model on a SageMaker endpoint with dedicated instances (ml.c7g for Graviton cost-efficiency or ml.inf2 on Inferentia2 for throughput-optimized inference). The model scores every transaction in the decision path before the balance decrement. Custom models outperform managed alternatives at this scale because you control feature engineering, model architecture, and inference latency.
Why API Gateway and Step Functions are absent from this design.
This is intentional, not an oversight. API Gateway adds measurable per-request overhead. Step Functions Standard adds 50–100ms per state transition due to backend state persistence. Even Step Functions Express adds 10–20ms per transition. In a 3–4 step authorization flow (validate → fraud check → decrement balance → respond), you’d burn 40–80ms in orchestration overhead alone. That’s your entire latency budget, gone on coordination, not computation.
At enterprise scale, orchestration is in-process. The application running on EKS executes all steps sequentially within a single request lifecycle, with persistent connection pools to MemoryDB, DynamoDB, and the SageMaker endpoint. Zero orchestration overhead.
Step Functions absolutely belong in this architecture, but not in the hot path. Use them for settlement batch processing, chargeback dispute flows, and merchant onboarding. These workflows run over hours or days, and the visual execution history, built-in retry logic, and declarative error handling are enormously valuable there.
Multi-region: active-active with region affinity.
For a system where downtime means money stops flowing, single-region is not an option. Deploy across two regions (e.g., sa-east-1 and us-east-1) with Route 53 latency-based routing. DynamoDB Global Tables handle cross-region ledger replication. MemoryDB Global Datastore handles balance cache replication.
The consistency challenge is real: eventual replication between regions means two concurrent transactions from the same account in different regions could both approve and overdraft the balance. The solution is region affinity by account. All transactions for a given account route to the same primary region. Failover to the secondary region only triggers during a regional disaster, with automated reconciliation after recovery.
Growth Tier (1k–50k TPS)
At this scale, the tradeoffs shift toward operational simplicity.
ECS on Fargate with ALB. The Layer 7 overhead of the ALB is acceptable when your latency SLA is 200–500ms. The operational gain (zero instance management, no Karpenter configuration, no kubelet tuning) is substantial.
DynamoDB on-demand. No capacity planning, no provisioned throughput tuning. Pay per request. At this volume, it’s cost-effective and eliminates the most common source of DynamoDB throttling incidents: under-provisioned tables.
SQS FIFO for transaction event ordering. When you need to guarantee that events for the same account are processed in order (balance updates, transaction logs), SQS FIFO with message group IDs partitioned by account gives you exactly-once processing with ordering guarantees.
Amazon Fraud Detector (Note: Since November 7th, 2025 Amazon doesn’t accept new customers to use AFD). Use SageMaker with AutoGluon instead (As a recomendation of AWS) of hand-rolled ML pipelines for this tier. Amazon Fraud Detector was the go-to managed option here, but AWS stopped accepting new customers in November 2025. The recommended path now is AutoGluon. An open-source AutoML library that trains competitive fraud models with minimal ML expertise and deployed on SageMaker endpoint. You lose the fully managed rule engine, but you gain flexibility and avoid dependency on a service with an uncertain roadmap.
Resiliency: Multi-AZ
Resiliency: Multi-AZ mandatory, multi-region as pilot light. The second region has infrastructure provisioned but powered down. Route 53 health checks trigger automated failover if the primary region degrades.
Startup Tier (Under 1k TPS)
API Gateway + Lambda + DynamoDB on-demand + EventBridge.
At low volume, Lambda cold starts are irrelevant (your SLA is generous), API Gateway’s built-in throttling and request validation are features rather than overhead, and DynamoDB on-demand costs almost nothing when idle.
EventBridge handles event-driven processing of downstream consequences (analytics updates, merchant notifications, webhook delivery) with content-based routing to multiple Lambda targets. It’s not in the authorization hot path; it processes what happens after the decision is made.
Monthly cost for this stack at low volume: potentially under $100.
The risk here is growth. If this startup goes from 100 TPS to 10k TPS in six months, this architecture needs a rearchitecture. Acknowledging that debt upfront and having a migration plan ready is better than over-engineering for scale that may never come.
Pix Authorization: The Push-Based Architecture
Now forget almost everything about the card model. Pix introduces constraints that don’t exist in card processing, and relaxes others that card processing takes for granted.
A Note on Maturity Tiers for Pix
Before going deep on the architecture, one clarification matters here. Not every company processing Pix connects directly to the SPI (Sistema de Pagamentos Instantâneos). Most fintechs, and practically all startups, operate through an indirect PSP (Payment Service Provider) , a bank or licensed institution that holds the direct SPI connection on their behalf.
If that’s your reality, your architecture looks radically different from what follows. You’re calling the PSP’s API over HTTPS. You don’t need Direct Connect, CloudHSM, or a hermetically sealed VPC. Your stack is closer to the card startup tier: API Gateway, Lambda, DynamoDB, and webhooks for settlement confirmation. The regulatory burden shifts largely to the PSP.
What follows in this section applies to direct SPI participants , banks, licensed payment institutions, and large PSPs that own the connection to Brazil’s Central Bank. If you’re building at that level, keep reading. If you’re not there yet, the growth path is understanding what you’ll eventually need when volume and regulatory ambition push you toward direct participation.
Connecting to the SPI
The SPI is the backbone operated by Brazil’s Central Bank (BCB). Connecting to it is non-negotiable in architecture terms.
RSFN connectivity via Direct Connect. The RSFN (Rede do Sistema Financeiro Nacional) is a closed, private network. There is no internet path to the SPI. On AWS, this means AWS Direct Connect with dedicated circuits to RSFN points of presence, with a minimum of two circuits in separate facilities for redundancy (mandated by the BCB). Direct Connect Gateway with Link Aggregation Groups (LAGs) provides the high availability layer, with BGP-based automatic failover if a circuit goes down.
Hermetically sealed VPC. The VPC (Virtual Private Cloud) that interfaces with the SPI has no internet gateway, no NAT gateway, no path to the public internet whatsoever. Traffic enters and exits exclusively through Direct Connect. Security Groups restrict to RSFN CIDRs. NACLs (Network Access Control Lists) provide the second enforcement layer. VPC Flow Logs stream to S3 with Object Lock for immutable audit trails.
Transit Gateway for segmented routing. The SPI VPC communicates only with the application VPC through Transit Gateway route tables. It never routes to other workload VPCs, shared services, or the internet. This segmentation isn’t just best practice; it’s an audit requirement.
CloudHSM for cryptographic operations. The BCB requires ISO 20022 messages to be digitally signed with ICP-Brasil certificates. CloudHSM (FIPS 140–2 Level 3, single-tenant) gives full control over key ceremony, key storage, and audit logging. AWS Payment Cryptography is an alternative, but most large Pix participants prefer CloudHSM for the total control over key lifecycle management.
Why ISO 20022 Uses XML (and Why It Matters Architecturally)
This surprises every developer who encounters it for the first time. The SPI message format is ISO 20022, which is XML-based, not JSON.
The reasons are technical, not arbitrary. XML has native schema validation via XSD that predates JSON Schema by nearly a decade and has 20+ years of tooling in financial systems. XML supports namespaces, allowing different message domains to coexist without field name collisions. More critically, XMLDSig (XML Digital Signature) supports signing specific sections of a document independently. In a multi-party financial flow, different institutions can sign their respective sections without invalidating each other’s signatures.
JSON has JWS (JSON Web Signature), which is mature and powers billions of OAuth/OIDC flows daily. But JWS signs the entire payload, not sections of it. And JSON’s canonicalization story (JCS, RFC 8785, published in 2020) is still young compared to XML’s C14N standard from 2001. The fundamental issue is that different programming languages can serialize the same JSON value differently (100.0 vs 1e2, key ordering variations), which breaks signature verification if canonicalization isn’t bulletproof.
The architectural implication: XML dies at the gateway. Your SPI gateway pods on EKS handle serialization/deserialization of ISO 20022, digital signature operations via CloudHSM, and translation to your internal format (JSON, Protobuf, whatever your microservices speak). This is a classic anti-corruption layer. The complexity of XML processing is isolated to a single boundary service, and 95% of your engineering team never touches it.
The Decision Engine for Pix
The payer’s bank validates before sending to the SPI. There’s no round-trip approval like in cards. Once the message goes to the SPI, the funds are committed. This means the validation logic carries more weight, because reversal after SPI submission is a multi-day MED (Mecanismo Especial de Devolução) process, not an instant void.
MemoryDB over ElastiCache is even more critical here. In Pix, settlement is instantaneous. The balance must be decremented before submitting to the SPI, and if the SPI rejects the transaction, the balance must be restored. If ElastiCache Redis loses a node between the decrement and the SPI response, you have a phantom balance: decremented but never settled, with no durable record of the pending state. MemoryDB’s durable transaction log eliminates this risk entirely.
DICT caching. The DICT (Diretório de Identificadores de Contas Transacionais) is the BCB’s directory mapping Pix keys to accounts. Every transaction requires a DICT lookup to validate the recipient’s key and retrieve their account details. The DICT is accessed through the SPI, adding network latency. Solution: cache DICT entries locally in DynamoDB with DAX, using a TTL of a few minutes. The BCB permits caching as long as you respect TTL limits and invalidate entries when key portability events occur.
Anti-fraud has unique Pix requirements. Beyond standard ML scoring (SageMaker endpoint), you must check DICT infraction markers (is the recipient’s account flagged for fraud?), enforce time-based limits (Pix has different value caps for nighttime transactions), and evaluate behavioral patterns (an account that never transacted at 3 AM suddenly executing 50 Pix transfers triggers mandatory blocking).
The velocity check is where MemoryDB shines again. “How many Pix has this account sent in the last 5 minutes?” is a sliding window query that Redis handles in microseconds. This must execute before SPI submission, in the hot path, with no tolerance for data store latency spikes.
The Thundering Herd Problem
This is the scenario that has caused real production incidents at Pix PSPs, and it doesn’t have an analog in card processing.
Consider: 500,000 customers schedule Pix payments for midnight on the rent due date. At 00:00:00, your system needs to initiate 500k transactions simultaneously.
If you poll a database for scheduled payments (SELECT * WHERE execution_time <= NOW()), the query alone can saturate your data store. A DynamoDB scan with filters would consume massive read capacity in a single burst.
The solution is SQS with delay and jitter. Scheduled Pix payments are enqueued in SQS well in advance, each with a randomized DelaySeconds between 0 and 300 seconds. This transforms a 500k TPS spike into a sustained ~1.7k TPS flow over 5 minutes. The BCB’s SLA gives you 10 seconds for settlement, so spreading over 5 minutes is invisible to the customer.
A more sophisticated alternative: EventBridge Scheduler with rate-based invocation. Define a rule that processes at most 2,000 scheduled Pix per second starting at 00:00, and the scheduler distributes automatically.
This pattern is uniquely important for Pix because the push-based model means customers control when payments fire. In card processing, transaction timing is naturally distributed across merchant activity. In Pix, cultural patterns (everyone pays rent on the same day, everyone sends money at midnight on salary day) create artificial spikes that the architecture must absorb.
Notification Layer: Event-Driven Fan-Out
After SPI confirmation, both payer and recipient need real-time notification. This is the asynchronous layer where EventBridge excels.
A single SPI confirmation event fans out to multiple consumers: push notification to the payer’s app, push notification to the recipient’s app, webhook to the merchant’s system, balance update in MemoryDB and DynamoDB, and analytics/compliance logging.
EventBridge routes by content (transaction type, value, merchant category) to different Lambda targets. For merchant webhooks specifically, place an SQS queue between EventBridge and the delivery Lambda. The merchant’s endpoint might be down, and SQS gives you retry with exponential backoff and a dead-letter queue for failed deliveries. Without this buffer, a merchant outage causes event loss.
Multi-Region: The RSFN Constraint
This is where Pix and card architectures diverge most sharply.
Card processing supports true active-active multi-region because the connection to card networks runs over the public internet with TLS. You can terminate in any AWS region.
Pix cannot. The RSFN has points of presence in São Paulo and Rio de Janeiro. Your Direct Connect circuits terminate there, which means your SPI integration VPC must be in sa-east-1.
The multi-region model for Pix becomes: sa-east-1 as the primary region for everything that touches the SPI (gateway, decision engine, ledger), with a secondary region (e.g., us-east-1) in warm standby exclusively for layers that don’t depend on the SPI (customer-facing app, account management, statement queries, merchant portal).
If sa-east-1 suffers a catastrophic failure, the SPI integration goes down regardless of your secondary region, because Direct Connect connectivity is physically bound to the RSFN. Resilience for the SPI path comes from Multi-AZ redundancy within sa-east-1 and Direct Connect circuit redundancy, not from multi-region failover.
What the Docs Don’t Tell You
Every section above has a clean narrative. Production doesn’t. Here are the things I’ve learned the hard way or seen break on teams that followed the documentation to the letter.
DAX is a read accelerator, not a write accelerator. The documentation says this, technically. But the mental model most developers carry is “DAX = DynamoDB but faster.” They put DAX in front of every DynamoDB call, including writes, and then wonder why their write latency went up. DAX intercepts the write, forwards it to DynamoDB, waits for confirmation, and then updates its cache. That’s an extra network hop on every write for zero benefit. If you’re using DAX, audit your write paths. If any of them route through DAX, you’re paying latency tax for nothing.
ElastiCache Redis is not MemoryDB, and the naming doesn’t help. I’ve watched a team design a Pix balance store on ElastiCache Redis because “it’s Redis and Redis is fast.” It is fast. It’s also not durable by default. A node failure between a balance decrement and the SPI response creates what I call a phantom balance , money subtracted from the customer’s view but never actually settled, with no durable record to reconcile from. MemoryDB’s Multi-AZ transaction log exists precisely for this scenario. The price difference is real, but so is the 3 AM incident when your reconciliation batch finds 12,000 orphaned transactions.
The thundering herd doesn’t show up in load testing. Standard load tests ramp traffic gradually. The Pix thundering herd doesn’t ramp. It detonates. 500k transactions at 00:00:00 on rent day is not a curve, it’s a wall. If your load test scenario is “increase from 0 to 500k TPS over 60 seconds,” you’ll pass with flying colors and still die in production. Test the wall: 0 to 500k in under 1 second. That’s what actually happens.
ALB latency is real, but the numbers depend on context. You’ll see claims of “single-digit millisecond” ALB overhead in isolation. That’s the ALB itself, processing a request with no complex routing rules on a warm target group. Add path-based routing with multiple rules, TLS termination with certificate evaluation, sticky sessions, and a target group that occasionally has unhealthy targets requiring failover , and the real-world overhead stacks up to meaningful levels when your total budget is 50ms. Don’t benchmark the ALB in isolation. Benchmark it with your actual routing configuration, your actual TLS certificates, and your actual target group dynamics.
Multi-region for Pix is a compliance conversation, not just an architecture one. Teams sketch out active-active across sa-east-1 and us-east-1 for Pix without realizing the RSFN constraint makes it physically impossible for the SPI path. The documentation mentions Direct Connect, but it doesn’t spell out that Direct Connect to the RSFN has fixed points of presence that anchor you to sa-east-1. I’ve seen architecture review boards approve multi-region Pix designs that would have failed on day one of integration testing.
PCI-DSS and Regulatory Compliance on AWS
Both architectures must address PCI-DSS Level 1 (mandatory for any payment processor), but Pix adds BCB-specific requirements on top.
Network segmentation: Dedicated VPCs for cardholder data environments, security groups restricted to minimum necessary ports, NACLs as defense-in-depth, and AWS Firewall Manager with WAF (Web Application Firewall) for any internet-facing surfaces.
Encryption: TLS 1.3 in transit everywhere. KMS (Key Management Service) with customer-managed keys (CMKs) for data at rest. AWS Payment Cryptography or CloudHSM for payment-specific cryptographic operations (PIN translation, card verification values, digital signatures).
Immutable logging: CloudTrail with organization-wide trails, logs shipped to S3 with Object Lock (WORM compliance), integrated with a SIEM for real-time monitoring. VPC Flow Logs for network-level audit.
Access control: IAM (Identity and Access Management) with strict least privilege, MFA enforced on all human access, temporary credentials via STS (Security Token Service) for all programmatic access, and AWS Private CA for internal mTLS between services.
Continuous scanning: Amazon Inspector for vulnerability assessment, GuardDuty for threat detection, Security Hub for consolidated compliance scoring. These aren’t optional add-ons; they’re table stakes for a QSA (Qualified Security Assessor) audit.
AWS is PCI-DSS Level 1 certified as a provider, but shared responsibility means your configuration must independently pass audit. The QSA will examine your infrastructure, not Amazon’s.
For Pix specifically, the BCB mandates 99.999% availability (five nines). That’s under 5 minutes of downtime per year. Achieving this requires a formalized chaos engineering program: AWS Fault Injection Service (FIS) for controlled failure injection, regular GameDay exercises simulating Direct Connect failures, CloudHSM cluster degradation, and DynamoDB throttling events. Five nines isn’t something you achieve by accident; it’s something you prove through repeated, documented testing.
Choosing the Right Architecture for the Right Maturity
The biggest mistake I see teams make is over-engineering for scale they don’t have, or under-engineering for growth they can’t predict.
A startup processing a few hundred Pix per minute doesn’t need EKS, MemoryDB, or Direct Connect. API Gateway, Lambda, and DynamoDB on-demand will carry them for months at minimal cost. But they should have a documented migration path to the growth tier, with clear triggers (TPS thresholds, latency percentiles, compliance requirements) for when to begin the transition.
A growth-stage fintech processing 10k TPS doesn’t need bare-metal EC2 with DPDK kernel bypass. ECS on Fargate with ALB handles this cleanly. But their data store choices and idempotency patterns should be designed to survive the jump to the enterprise tier without a full rewrite.
And an enterprise processor handling hundreds of thousands of TPS per second can’t afford abstraction layers that trade latency for convenience. Every millisecond is a business decision, every data store choice is a consistency decision, and every architectural shortcut is a compliance risk.
The architecture should match the business, not the other way around.
# financial-services# financial-services-industry# finance# aws-cloud-financial-management# amazon-eks
Series: Golden Jacket Field Notes (22 articles)
- …
- 7Payment Authorization on AWS: Credit Cards vs. Pix at Scale This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article