ApiFuel
Lead management and dispatch · 2012 — 2025
Operated 2012 — 2025
Ingests leads and dispatches each one to multiple third-party buyer APIs. The interesting part is not the request rate — it is that every lead multiplies into several outbound calls.
- Inbound load tested
- ~10k requests over ~4 minutes
- Outbound workers
- ~300 per instance
- Peak fleet
- ~30 instances (hard cap 50)
- Instance type
- AWS t4g.small
The constraint that shaped everything
A lead arrives once and leaves several times: each one is dispatched to multiple buyer APIs, each of which can fail, slow down or reject independently. That makes capacity a function of outbound concurrency, not of how many requests arrive per second. Optimising inbound throughput would have solved the wrong problem.
Three architectures, same product
Native PHP built for throughput under shared hosting (2012). Then AWS Lambda and API Gateway (2016), trading server administration for managed scaling and accepting cold starts. Then a rebuild of the dispatch layer in TypeScript with BullMQ and a Redis Cluster (2025), because the queue semantics and visibility the previous stack could not give me were now the requirement.
Scaling ahead of demand instead of reacting to it
A new t4g.small takes one to two minutes to become ready, and the traffic bursts I designed for last about four. A reactive autoscaler would deliver capacity after the burst was already over. So a controller watches live concurrency and provisions workers ahead of the curve, with the trigger threshold calibrated from load tests rather than guessed. The hard cap of fifty instances is a cost guardrail, not a technical limit.
How the numbers were obtained
Automated campaigns sending POSTs, with concurrency, queue depth and database connections read from CloudWatch, Bull Board and PgBouncer. This was a load test, not customer traffic — the distinction matters and I keep it explicit.
PHP · TypeScript · AWS Lambda · API Gateway · BullMQ · Redis Cluster · PostgreSQL · PgBouncer