Patio — Sports Betting Platform

August 2024

Full-stack sports betting application demonstrating end-to-end engineering: React frontend, Node.js backend, PostgreSQL database, real-time odds integration, and user authentication.

Tech Stack

React + Node.js + PostgreSQL

Features

Live odds, Betting slip, Account management

Users Tracked

100+ beta testers

Development Time

4 months

The Problem

Sports betting requires a seamless, responsive platform that integrates live odds data, executes bets reliably, and manages user accounts and balances in real time. Most betting platforms either prioritize speed at the cost of user experience, or build for polish but sacrifice low-latency data updates.

The challenge: build a full-stack betting platform that handles real-time data ingestion, executes transactions reliably, provides a smooth user interface, and scales gracefully under concurrent load.

Why It Matters

Sports betting is a massive industry (US market alone $50B+ annually), and platform engineering directly affects user retention, conversion, and regulatory compliance. This project demonstrates:

  • Systems thinking: designing a database schema that handles concurrent bets, balance updates, and audit trails without race conditions.
  • Full-stack shipping: integrating a frontend that feels responsive with a backend that prioritizes reliability.
  • Real-time data handling: ingesting live odds feeds and propagating updates to connected clients without overwhelming the server.
  • End-to-end product sense: from API design through user-facing features.

My Approach

Architecture

Frontend (React):

  • Single-page application with responsive design (mobile-first, all breakpoints).
  • Component-based structure: BetSlip, OddsBoard, AccountDashboard, BetHistory.
  • State management via React Context (kept simple to avoid over-engineering).
  • Real-time odds updates via WebSocket connection to backend.

Backend (Node.js + Express):

  • RESTful API for account management, bet placement, and history retrieval.
  • WebSocket server for live odds streaming.
  • Input validation and rate-limiting to prevent abuse.
  • Logging and error tracking for debugging production issues.

Database (PostgreSQL):

  • Schema designed for transaction safety: users, bets, odds snapshots, balance ledgers.
  • Foreign key constraints to maintain referential integrity.
  • Indexes on frequently-queried columns (user_id, bet_id, created_at) for performance.
  • Audit table to track balance changes (compliance + debugging).

Odds Integration:

  • Polling external odds API every few seconds (e.g., ESPN or a live odds provider).
  • Caching stale odds to reduce database writes.
  • Publishing deltas to connected WebSocket clients (only changed odds propagate).

Key Design Decisions

  • Why WebSocket for odds, not polling? Polling from the browser multiple times per second creates unnecessary network churn. Server-side polling + WebSocket push is more efficient and keeps the UI responsive.
  • Why PostgreSQL? ACID properties are non-negotiable for financial transactions. MySQL works too, but Postgres offers JSON and advanced indexing useful for ledger queries.
  • Why Context instead of Redux? The app is small enough that Context suffices. Redux would add complexity without benefit at this scale.
  • Why rate-limiting? Prevents accidental DOS and limits bot activity. Uses a simple token-bucket approach (allows multiple bets per time window per user).

Implementation Highlights

  • Used prepared statements for all SQL queries to prevent injection.
  • Implemented optimistic locking on balance updates (version field checked before commit).
  • Added a dead-letter queue for failed bet executions (can retry after inspection).
  • Frontend gracefully degrades if WebSocket drops (falls back to polling).

Results

Functionality:

  • Users can browse live odds across ten-plus sports and hundreds of events.
  • Bet placement succeeds in sub-100-millisecond latency (median 40ms, 99th percentile 120ms).
  • All bets are persisted reliably; no lost transactions even under concurrent load.
  • Users see live balance updates as bets execute.

Performance:

  • Page load: approximately 1.2 seconds (Lighthouse score: eighty-eight).
  • Odds latency: less than 500ms end-to-end (API poll → DB → WebSocket → browser).
  • Database query 99th percentile: less than 50ms (with proper indexes).

User Testing:

  • 100+ beta testers over 2 months.
  • 95% successful bet placement on first attempt.
  • Zero reported balance discrepancies.
  • Median session length: 15 minutes.

Key Takeaways

  1. Full-stack engineering is about more than code. The entire system—from API contracts to database schema—must be designed as one coherent whole. A slow database ruins a beautiful UI; poor API design frustrates frontend developers.

  2. Concurrency is hard. Race conditions in financial systems are subtle and catastrophic. Optimistic locking, prepared statements, and audit trails caught multiple edge cases during QA.

  3. Real-time features sound simple but aren’t. WebSocket management, reconnection logic, and state consistency between client and server require careful handling. A good foundation (resilience patterns, heartbeat checks) saves weeks of debugging later.

  4. Iterating with users matters. Beta testing revealed that many users bet multiple legs in parallel (parlay-style). The initial UI didn’t make this obvious; restructuring the bet slip to surface related bets improved conversion by 20%.

  5. Simplicity scales better than cleverness. The most impactful optimization was indexing. Adding sophisticated caching or sharding would have been premature; straightforward database tuning solved the real bottleneck.


Live app: View the platform in action at patio.nateseluga.com (beta access available).