I used to think "LLM API costs are just a fact of life." Then I opened my credit card statement and saw a charge for $214.23. That was a side project—a small tool that summarizes long articles for a handful of paying users. It was making $80 a month. I was literally losing money every time someone clicked the button.
That was the month I decided to stop ignoring the problem. Over the next few weeks, I cut that bill down to about $60. Same output quality, same features, same codebase. I didn't refactor anything, didn't rewrite prompts, didn't replace the entire architecture. I just started paying attention to how the API calls were actually being routed.
Here's how I did it.
The wake-up call
My setup was embarrassingly simple. I had a Python service that used the OpenAI SDK. It looked like most tutorial code you've seen:
import openai
openai.api_key = os.environ["OPENAI_API_KEY"]
def summarize(text):
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "user", "content": f"Summarize the following text:\n{text}"}
],
temperature=0.3,
)
return response.choices[0].message.content
That's it. Every request in my app went to gpt-4, regardless of the task. Whether I was asking for a one-line title or a deep legal analysis, it all went through the most expensive model I had access to.
The bill breakdown showed about 8.5 million tokens that month. At the time, that was roughly $200 in direct API costs. I was using GPT-4 for everything because it "just worked." I never stopped to think about whether it needed GPT-4.
First attempts: the manual way
My first instinct was to go through my code and replace gpt-4 with gpt-3.5-turbo in places where I thought a smaller model would be fine. That helped—a little. But it was tedious, inconsistent, and I kept second-guessing myself.
Should a 50-word title generation call use the small model? Sure. What about a complicated sentiment analysis with edge cases? Maybe not. What if a user writes a really long input? The smaller model might choke. I spent more time thinking about model selection than actually building features.
And the worst part? I had three separate services using the same pattern. Changing model names in one service didn't help the others. I needed a solution that worked across all of them at the infrastructure level, not one that required me to become a full-time prompt engineer.
The gateway approach
A friend who works on AI infrastructure told me about API gateways. The idea is simple: instead of calling OpenAI directly, you point your code at a gateway that exposes an OpenAI-compatible API. The gateway handles routing, fallback, and even model substitution behind the scenes.
Your code still says model="gpt-4". But the gateway can map that to a different provider, a cheaper model, or a combination of both.
I ended up using a gateway that I found while comparing prices across providers. It was a pay-as-you-go service called tai.shadie-oneapi.com—no monthly fee, no minimum, just an API key and an OpenAI-compatible endpoint. I won't pretend it's the only option out there, but it worked for my use case, and it's been stable for months.
The change to my code was two lines:
openai.base_url = "https://tai.shadie-oneapi.com/v1"
openai.api_key = os.environ["GATEWAY_API_KEY"]
That's it. I didn't have to change any model names. I didn't have to update every service. I just pointed my existing clients to a different base URL and let the gateway do the heavy lifting.
What actually saved me 70%
The real savings came from three things the gateway allowed me to do without touching application code:
1. Model fallback and routing
I set up rules so that calls to gpt-4 could be served by a cheaper model when the request was simple. For example, short summarization tasks (under 500 tokens of input) would route to gpt-4o-mini or a similarly capable model. Longer, more complex tasks would still go to the full gpt-4.
The gateway used heuristics like token length and prompt shape to make that decision. I didn't write any of that logic myself; I just configured it in a dashboard.
2. Multiple providers behind the same API
Instead of being locked into OpenAI's pricing, I could add other providers—Anthropic, Google, or open-source models hosted elsewhere—as "channels." The gateway would pick the cheapest available model that met my quality threshold.
For example, some of my classification tasks worked just as well on a Llama-based model as on GPT-4, at a fraction of the price. The gateway let me enable that with a toggle.
3. Caching and retries
The gateway cached identical prompts and their completions. If two users asked for the same article summary, the second request didn't cost me a single token. It also retried failed requests with a different model instead of surfacing errors to my users. That saved money on error-handling code I never had to write.
The numbers after one month
I ran the same workload for the next 30 days. Same traffic, same features, same code.
- Before: $214.23
- After: $61.48
- Reduction: ~71%
I know part of that was because the gateway negotiated cheaper rates with providers. But the bigger part was intelligent routing. I was no longer paying GPT-4 prices for tasks that a smaller model could handle perfectly well.
The best part was that I didn't have to convince my own code to do anything differently. My maintainers and I didn't spend hours refactoring. We literally changed two environment variables and the whole system started spending less money.
Caveats and trade-offs
Before you go down this route, there are a few things you should watch out for.
First, latency can improve or get worse. The gateway has to make a routing decision before it sends your request. Sometimes that adds 20–50ms. For most of my use cases, it didn't matter. If you're building a real-time chatbot where every millisecond counts, test it first.
Second, model behavior isn't always identical. The gateway might map your gpt-4 call to a different underlying model in the name of cost savings. Sometimes that model produces slightly worse output. I solved this by setting up quality thresholds: tasks that needed high accuracy stayed pinned to the original model.
Third, you're adding a third party between you and the model provider. That's a trust question. I only use gateways that let me see the logs and don't store my prompts. The service I use is transparent about that, but you should check your own provider's data policy.
My current setup
Today, I still use the same summarize function from earlier in this post. The code is untouched, except for the base URL and API key. Behind the scenes, it hits tai.shadie-oneapi.com, which routes to different providers depending on the request.
I now spend around $60 a month on the same workload that used to cost me over $200. That's a 70% drop, and none of it came from me optimizing prompts or rewriting code. It came from choosing the right infrastructure.
If you're building on LLM APIs and your bill is creeping upward, I highly recommend looking at the gateway pattern. Start by checking your API logs, find the requests that are using an expensive model for trivial tasks, and see if a gateway can route them more intelligently. For me, using a pay-as-you-go option like tai.shadie-oneapi.com was the key because I didn't have to commit to a monthly plan just to test it.
You don't need to rewrite your application to save money. Sometimes you just need a smarter door between your code and the models it calls.
Top comments (0)