I raced six models against each other on DigitalOcean Inference. The cheapest one won. A developer built a 390-line Python tool to race six AI models against each other on DigitalOcean's Inference endpoint, streaming responses side by side with time-to-first-token and cost metrics. The benchmark revealed that gunicorn's default sync worker serialized concurrent streams, making models appear slow, and switching to threaded workers cut total time from 10.7 to 6.4 seconds. The cheapest model, Mistral 3 14B, won on both latency and cost. Every time I put a model behind an endpoint I make the same lazy decision. I pick whatever I used last time, or whatever I read about most recently, and I tell myself I'll benchmark it properly later, and later never arrives because there is always something with an actual deadline on it and comparing model latencies feels like procrastination even when it isn't. I never do it. Not once. So I built the thing that would make me do it. One prompt, fired at six models at once, streaming side by side in columns, with time to first token and cost per run underneath each one. About 390 lines of Python. Code's here https://github.com/oceanforge/inference-shootout , MIT, take it. Then I ran it, and three things happened that I didn't plan for. DigitalOcean's inference endpoint speaks OpenAI, so this is the whole thing: client = OpenAI base url="https://inference.do-ai.run/v1/", api key=os.environ "DIGITAL OCEAN MODEL ACCESS KEY" , Every model below goes through that one client. Llama, DeepSeek, Mistral, Qwen, OpenAI's open-weight gpt-oss line. Only the model string changes. That is the pitch, and it's real, and I'll move past it quickly because you already knew an OpenAI-compatible endpoint would work like an OpenAI- compatible endpoint. What I didn't know is everything that follows. One footnote before you paste that snippet. The credential is a model access key , created under the Gradient AI Platform. It is not the API token from Settings, API. Different thing, different page. Although, as I found out later, the endpoint doesn't care nearly as much about that distinction as the docs do. I wanted the columns to fill simultaneously. Real racing, not six sequential progress bars pretending. The tidy way to do that is one endpoint that fans out server side and multiplexes everything back down a single connection. I didn't do the tidy way. The browser opens one EventSource per model instead: GET /stream?model=