Alahubs Checkout
Dedicated payment microservice with Stripe and Mercado Pago. Processes USD subscriptions and BRL orders with idempotency, Discord alerts and Meta Ads lead attribution.
2024ProductionFounder & Full-Stack ArchitectSaaSPaymentsFintech
- NestJS
- TypeScript
- PostgreSQL
- Stripe
- Mercado Pago
- Docker
- Kubernetes
- Meta Ads
- Discord API
2500+ users
5k+ transactions/day
<500ms processing
Stripe + Mercado Pago
Impact
- Isolated NestJS service from the main Alahubs platform, enabling independent payment scaling and updates without affecting user operations.
- Stripe for USD subscriptions and Mercado Pago for BRL orders unified into a single processing endpoint. Idempotency keys prevent double-charging; nightly cron reconciles ledgers between both processors.
- Native pg driver with 20-connection pool replacing Prisma ORM, with 15% latency improvement. Parameterized queries, atomic transactions and repository pattern for data access abstraction.
- Real-time alerts via Discord webhook for failures and successful transactions. Lead attribution with SHA256-hashed PII sent to the Meta Pixel API.
KPIs
Entities modeled
4 (Products, Purchases, Cards, Coupons)
Connection pool
20 connections
Processors
Stripe + Mercado Pago
Average latency
<500ms
Daily transactions
5k+
Currencies supported
USD, BRL
Event integrations
Discord, Meta Ads
Coupon types
Fixed, Percentage
Traction & Growth
Active Users
2500+
Paying Customers
120+
Monthly Price
R$ 49.95 to R$ 499.95
MRR
~R$ 40k - R$ 60k
Acquisition Channel
Alahubs organic + Meta Ads
Processes all Alahubs subscription revenue. Payment success rate above 98.5%. Mercado Pago leads in LATAM markets; Stripe in US/EU. Estimated LTV $250+ based on 12-month retention.
Architecture
alahubs-checkout-architecture
Key Decisions
- Native pg driver instead of Prisma ORM: Manual SQL increases maintenance cost, but eliminates ORM overhead and schema drift. 15% latency improvement for high-volume payment processing.
- Repository pattern for data abstraction: One extra indirection layer, but makes testing easier and allows swapping the database without touching business logic.
- Single payment endpoint with internal provider routing: Simplifies frontend integration, but requires careful error mapping: Stripe and Mercado Pago return completely different response formats.
- Synchronous payment processing without a job queue: Endpoint blocks until the provider responds (latency over 500ms). Less operational complexity, but vulnerable to external API slowness. Bull or RabbitMQ would fix this.
Hard Problems
- Stripe uses subscriptions in USD; Mercado Pago uses orders in BRL with no native subscription model. A BillingType enum and provider-specific logic inside PaymentsService handle the mapping. Mercado Pago subscriptions are emulated with recurring order creation and scheduled checks.
- SQL queries without an ORM require manual parameter binding. Query builder utilities with strict TypeScript interfaces maintain type safety without relying on Prisma.
- A single request can contain multiple products with different discounts. The coupon repository tracks which products each coupon applies to; the calculation sums per-product reductions before processing payment.
- Meta Ads requires user email and name for lead attribution, but that data cannot be stored in plaintext. SHA256 hash applied at payment request time; hashed values sent to the Pixel. Raw PII never written to the database.
- The 20-connection pool can exhaust under load. Pool metrics monitored with alerts at 80% utilization. Non-critical requests rejected gracefully when the pool is near capacity.
Ops & Runbook
- Stripe is the primary processor; Mercado Pago is the fallback. Circuit breaker activates after 3 consecutive failures. Manual reset via /admin/circuit-breaker/reset.
- Connection pool monitored via Datadog APM. Alert if utilization exceeds 80% for more than 5 minutes. Response: scale horizontally or investigate slow queries.
- Discord and Meta Ads webhooks fire asynchronously after successful transactions. Retries with exponential backoff (1s, 2s, 4s). Persistent failures go to a DLQ table.
- Product cache with 1-minute TTL. Manual invalidation via /admin/cache/invalidate?entity=products. Changes propagate to replicas within 30s.
- Nightly cron at 03:00 UTC compares local ledger with Stripe invoices and Mercado Pago orders. Discrepancies trigger a Slack alert.
Security & Privacy
- DTOs decorated with class-validator reject malformed requests before any processing.
- All queries use pg parameter binding ($1, $2). Dynamic SQL concatenation not permitted.
- Coupons identified by slug, not sequential integer IDs. Prevents brute-forcing. Creation restricted to admin endpoints with role guards.
- Stripe secret key never hardcoded or logged. Quarterly rotation via CI/CD secrets manager.
- All Stripe webhooks validated via sig_* header before any processing.
What I'd Improve Next
- Replace synchronous processing with Bull or RabbitMQ queues. The endpoint would return immediately; workers would process the transaction in the background.
- Automatic retries with exponential backoff for transient network failures without manual intervention.
- Immutable transaction ledger for complete audit trail and dispute resolution without relying on third-party APIs.
- Self-service portal for customers to manage invoices, payment methods and subscription tiers.