Senior Backend Engineer · Real-time Systems · Pickles Asia

Bidding Engine Redesign
Redesign the entire RTC architecture, achieving 1M+ daily transactions.

Pickles Asia's live vehicle auction platform ran on a single-node Socket.io v2 server with no Redis adapter and no horizontal scaling path. During peak bidding events, the server had no way to distribute connection load across containers, causing drops and lag under pressure. Working on an 8-year-old production codebase where P1 incident response and new feature work competed for the same bandwidth, I redesigned the entire real-time communication layer. Upgraded Socket.io to v4, integrated the @socket.io/redis-adapter for pub-sub state synchronisation across all container instances, and deployed the fleet to AWS ECS Fargate with auto-scaling. The platform now handles 1M+ daily transactions at 99.99% uptime with rolling zero-downtime deployments.

bidding.engine.productionLive
99.99%
Uptime
1M+
Txns/day
+40%
Reliability
50%
Deploy ↓
throughput · stable ↑
The Challenge

A single-server bottleneck with no horizontal scaling path

The bidding engine was a single Node.js process handling all WebSocket connections for live vehicle auctions. Running Socket.io v2 with no Redis adapter, every server instance was completely isolated - no shared state, no cross-container event propagation. During peak auction events when hundreds of concurrent bidders connected, the single server had nowhere to go. You couldn't add a second container without splitting the connection pool, meaning bidders on one instance couldn't receive events published by the auction engine on another. The system had been in production for 8 years. Incremental patches had held it together, but the architectural ceiling was real.

  • Socket.io v2 with no Redis adapter - each container instance was a completely isolated silo
  • Single-server architecture with no horizontal scaling path under peak auction load
  • Peak bidding events causing connection drops and latency spikes for active bidders
  • Manual deployments requiring brief outages - no zero-downtime deployment strategy
  • No pub-sub mechanism between the bidding platform and RTC server

rtc_server.statusDegraded
↑ spike
Connection drops
1 node
Capacity
manual
Deployment
Scaling strategyVertical only
Downtime per deploy~5 minutes
Scalability ceilingHard limit
The Solution

A distributed, container-native RTC architecture on ECS Fargate

1
Socket.io v2 → v4 upgrade - Unlocked Redis adapter and improved stability:
  • Upgraded socket.io and socket.io-client from v2.x to v4.x
  • Official Redis adapter now available (v2 had workarounds)
  • Improved connection reliability and reconnection algorithm
  • More stable WebSocket handshake under poor network conditions
2
Redis adapter for stateless horizontal scaling - All containers share a common pub-sub channel:
  • Integrated @socket.io/redis-adapter
  • Every ECS container instance shares Redis pub-sub
  • Event broadcast → all clients across entire fleet
  • No silo, no state drift, no missed auction events
3
Horizontal auto-scaling on ECS Fargate - Distribute connection load automatically:
  • Containerized RTC server
  • Deployed to ECS with auto-scaling on ALB connection count & CPU
  • Multiple containers run in parallel
  • Coordinated staging validation for realistic concurrency testing
4
Structured logging across socket lifecycle - Turn incident response from blind guessing to tracing:
  • Added structured JSON logging across all socket events
  • Logged: connect, disconnect, broadcast, error, auction state
  • Before: 'users can't bid' → hours of grepping
  • After: root cause identification in under 10 minutes
5
ECR image pipeline and zero-downtime CI/CD - Automated builds and graceful deployments:
  • AWS ECR with automated builds via GitHub Actions
  • ECS rolling deployments with graceful connection draining
  • New tasks drain connections before replacement (zero downtime)
  • Docker layer caching + parallelized tests = 50% faster pipeline
New Architecture Overview
Web AppNext.jsMobile AppReact NativeWebSocket · Socket.io v4AWSApplication Load BalancerSticky sessions · Health checks · WebSocket upgradeECS FARGATE CLUSTER · AUTO-SCALINGliveRTC Node 1Socket.io v4 : 3000liveRTC Node 2Socket.io v4 : 3000RTC Node Nauto-scaled···pub-sub eventsREDIS ELASTICACHE@socket.io/redis-adapter · Pub-sub · Session cacheauction eventsE-BIDDING PLATFORM API · NODE.JSAuction engine · Business logic · RDS PostgreSQL
Resilience & Failure Handling
AWSApplication Load BalancerHealth checks every 30s · Sticky sessions · WebSocket upgradeAZ-1 · ap-southeast-1aliveRTC Node ASocket.io v4 · healthy:3000 · serving connections×TASK FAILEDRTC Node Btask stopped · deregistered→ traffic rerouted to AZ-2AZ-2 · ap-southeast-1bliveRTC Node CSocket.io v4 · healthy:3000 · + rerouted trafficSTARTINGRTC Node DECS replacing failed taskhealth check pending...REDIS ELASTICACHE · MULTI-AZPrimary (AZ-1) <-> Replica (AZ-2) · auto-failover < 30sFAILURE RECOVERY SCENARIOS1Node crash recoveryTask fails ×→ALB deregisters→ECS replaces ✓~ 30s2Zero-downtime rolling deployDrain conns→New task up→Old terminated ✓0s ↓3Redis primary failoverPrimary ×→Replica promoted→Pub-sub resumes ✓< 30s
The Results

From fragile to enterprise-grade

1M+
Transactions/day

Peak daily transaction volume handled reliably after the redesign, up from unpredictable performance under the old architecture.

99.99%
Uptime SLA

The new horizontally scaled deployment achieves near-perfect uptime, meeting all architectural and SLA requirements.

40%
Reliability boost

System reliability and scalability improved by 40% - measured across connection stability, error rates, and deployment consistency.

50%
Faster deploys

CI/CD pipeline optimisation via Docker layer caching and automated test parallelisation cut deployment time in half.

Engineering Decisions

Architectural choices, tradeoffs, and what nearly broke production

Socket.io v2 → v4, not Kafka

Why not use Kafka for the pub-sub layer?

Socket.io + Redis adapter is purpose-built for real-time WebSocket state sync with subsecond latency. Kafka is designed for durable event streaming and offline replay; overkill here. Redis pub-sub + adapter keeps operational complexity low and leverages an existing cache layer.

ECS Fargate, not Kubernetes

Why not Kubernetes for container orchestration?

ECS Fargate removes container node management entirely. Since Pickles Asia already uses AWS, Fargate eliminated operational overhead compared to running a K8s cluster. For this scale, Fargate's auto-scaling policies and simpler networking were the faster path to production.

What nearly failed: Connection state explosion

What almost broke during the migration?

During initial staging load testing, Redis connection pooling was misconfigured. Under peak load, the pub-sub layer created a new connection per event, exhausting Redis connection limits within minutes.

Root cause: connection pool size mismatch across Socket.io versions.

Lesson: Test under realistic concurrency patterns before production. Connection limits are silent killers in distributed systems.

Logging was the hidden blocker

What feature proved unexpectedly critical?

Structured JSON logging across socket lifecycle events. Without it, P1 incidents were impossible to diagnose; just 'users can't bid.' Added comprehensive logging for connect, disconnect, broadcast, and error events. This turned hour-long incident response times into 10 minutes.

THE TRADEOFFS

Cost · Risk · Tradeoffs

Estimated values based on production metrics and monitoring data

Cost Impact
~35% ↓
AWS compute cost reduction
Fargate auto-scaling eliminates idle capacity; formerly had to provision for peak even during off-peak hours
Risk Reduction
high → low
Deployment risk
Rolling deployments replaced manual outages; zero-downtime deploys eliminated auction platform downtime
Technical Tradeoff
eliminated
Single point of failure (RTC server)
Trade: added Redis as new dependency. Mitigated by Multi-AZ RDS setup and automated failover monitoring
Before vs After

Transformative Results: Before vs After

✕Before
  • Single server architectureLow scalability
  • Polling-based communicationHigh latency
  • Manual deploymentsSlow releases
  • Limited fault toleranceFrequent downtime
  • Monolithic codebaseHard to maintain
→
✓After
  • Distributed, container-native architectureHighly scalable
  • Pub-sub with RedisReal-time updates
  • CI/CD with automated deploymentsFast & reliable
  • Multi-AZ with auto-scalingHigh availability
  • Modular microservicesEasier maintenance
⇪Business Impact
40% improvement in reliability
50% reduction in deployment time
1M+ daily transactions supported
Tech Stack

What was used

RuntimeNode.js · TypeScript
Real-timeSocket.io v4 (from v2)
Redis Adapter@socket.io/redis-adapter
Cache / Pub-SubRedis
ContainersDocker · AWS ECR
OrchestrationAWS ECS · Fargate
CI/CDGitHub Actions
MonitoringDynatrace · CloudWatch
Frontend clientsVue.js · React Native

Need a scalable real-time system?

I've done this on a live production platform handling 1M+ daily transactions. Let's talk about your architecture and what it needs to handle peak traffic reliably.