DEV Community

bolddeck
bolddeck

Posted on

How I Cut My AI Bill By 97% and What I Learned Along the Way

How I Cut My AI Bill By 97% and What I Learned Along the Way

I genuinely had no idea how much money I was wasting on AI APIs until I sat down and actually did the math. Like, I knew it was expensive, but when I added up what my side project was spending versus what it could be spending? I was shocked. My jaw actually dropped.

I graduated from a coding bootcamp about eight months ago, and I've been building little projects nonstop. Most of them use AI in some way — chatbots, summarizers, code helpers, you name it. I always just reached for GPT-4o because, well, it's GPT-4o. Everyone talks about it. It works. Why would I use anything else?

Oh man. That was such an expensive mindset.

Let me walk you through what I learned, because if you're like me — a dev who just grabs the famous model without thinking — you might be hemorrhaging cash too.


The Moment I Realized I Was an Idiot

It started when my OpenAI bill hit $312 in one month. For a hobby project. I was building a customer support helper for a friend's e-commerce site, and I had it running on GPT-4o for everything. Every single request, even the dumb ones like "what are your shipping hours?"

I went down a rabbit hole that night. I read blog posts, watched YouTube videos, joined Discord servers, the whole thing. And what I found blew my mind: there are models out there that cost literally pennies compared to GPT-4o, and for most of what I was doing, they're totally fine.

Like, I had no idea that Qwen3-8B costs $0.01 per million tokens. ONE CENT. For comparison, GPT-4o is $10.00 per million output tokens. Do the math on that. I had to pull out my phone calculator because I didn't believe it.

That's a 99% difference. I'm not making that up.


My First Big Lesson: Stop Using One Model for Everything

This was the biggest thing that changed my thinking. I always treated "the AI API" as one thing, like flipping a switch. But different models are good at different things, and using a giant expensive model for simple stuff is like hiring a surgeon to put on a bandaid.

Here's a table that genuinely rewired my brain:

What I'm Doing What I Used What I Use Now Savings
Basic chatbot GPT-4o ($10/M) DeepSeek V4 Flash ($0.25/M) 97.5%
Sorting emails GPT-4o-mini ($0.60/M) Qwen3-8B ($0.01/M) 98.3%
Writing code GPT-4o ($10/M) DeepSeek Coder ($0.25/M) 97.5%
Summarizing articles GPT-4o ($10/M) Qwen3-32B ($0.28/M) 97.2%
Translating text GPT-4o ($10/M) Qwen-MT-Turbo ($0.30/M) 97%

I just stared at that for like ten minutes. Ninety-eight point three percent savings on classification? How is that even possible?

So I made myself a little routing function. Nothing fancy. I use Global API for this stuff because they let me access all these models through one endpoint, which keeps my code way cleaner. Here's what my model picker looks like:

MODEL_MAP = {
    "chat": "deepseek-v4-flash",          # $0.25/M
    "code": "deepseek-coder",          # $0.25/M
    "simple": "Qwen/Qwen3-8B",         # $0.01/M
    "reasoning": "deepseek-reasoner",   # $2.50/M
}
Enter fullscreen mode Exit fullscreen mode

Then I wrote a tiny classifier that picks the right model based on what the user is asking. Most of the time it picks something cheap. Only when someone asks a real brain-melter does it go for the expensive reasoning model.


The Tiered Routing Trick That Saved Me Hundreds

Okay, this is where things got really fun. There's this technique where you don't pick one model — you pick a sequence. You start with the cheapest possible model, check if the answer is good enough, and only escalate to something fancier if you have to.

I was shocked at how often the cheap model is "good enough." Like, embarrassingly often. I'd say 80% of the time, the smallest model gives a perfectly usable response.

Here's roughly how I structured it:

import requests

API_KEY = "your-global-api-key"
BASE_URL = "https://global-apis.com/v1"

def call_model(model_name, prompt):
    response = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "model": model_name,
            "messages": [{"role": "user", "content": prompt}]
        }
    )
    return response.json()

def smart_generate(prompt):
    resp = call_model("Qwen/Qwen3-8B", prompt)
    if quality_check(resp) >= 0.8:
        return resp  # Most requests stop here

    # Tier 2: Standard at $0.25/M
    resp = call_model("deepseek-v4-flash", prompt)
    if quality_check(resp) >= 0.9:
        return resp

    # Tier 3: Premium at $0.78-$2.50/M
    return call_model("deepseek-reasoner", prompt)
Enter fullscreen mode Exit fullscreen mode

The quality_check part is its own little rabbit hole. I started simple — just checking if the response was empty, or if it was way too short, or if it had obvious "I don't know" hedging language. You can get fancier with embedding similarity scores or even asking another model to grade it, but even basic checks made a huge dent.

I read about a customer support chatbot that was costing $420 a month. After they put in tiered routing, they were sending 85% of their traffic through Qwen3-8B. Their bill dropped to $28 a month. TWENTY-EIGHT DOLLARS. From four hundred and twenty.

I tried the same thing on my own project and cut my bill by about 93% the first month. I almost cried.


Caching: The Free Money I Was Leaving on the Table

This one made me feel dumb because it's so obvious in hindsight. People ask the same questions over and over. "What's your return policy?" "Where do you ship?" "Do you have this in red?" If you're hitting the API every single time, you're literally paying for the same answer repeatedly.

So I built a cache. It's like 15 lines of code:

import hashlib
import json
import time

cache = {}

def cached_chat(model, messages, ttl=3600):
    key = hashlib.md5(
        json.dumps({"model": model, "messages": messages}).encode()
    ).hexdigest()

    if key in cache:
        entry = cache[key]
        if time.time() - entry["time"] < ttl:
            return entry["response"]  # Cache hit, zero cost

    response = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={"model": model, "messages": messages}
    ).json()

    cache[key] = {"response": response, "time": time.time()}
    return response
Enter fullscreen mode Exit fullscreen mode

I set the TTL (time-to-live) to an hour because for my use case that's plenty. If you have stuff like news or live data, you'd want a shorter window, but for FAQs and how-to questions, an hour is fine.

What kind of hit rates am I seeing? Depends on the day, but the FAQ-style stuff in my friend's support bot hits the cache about 60-70% of the time. That's 60-70% of requests costing me literally nothing. Free money. Just sitting there.

If you want to go fancier, you can do semantic caching — instead of exact match, you find responses that are similar to what you're asking. Embeddings and a vector store. I haven't built that yet but it's on my list.


Shrinking My Prompts Saved Me Another Big Chunk

Okay, this one I had no idea about. Every token you send costs money. Every single one. So if my system prompt is 2,000 tokens but I really only need 400 of them to get the same result, I'm paying for 1,600 tokens of pure waste.

I had this monster prompt for my summarizer. It had all these instructions, examples, edge cases, formatting rules... it was like a whole essay. Then I started using a cheap model to compress my own prompts.

def compress_prompt(text, target_ratio=0.5):
    if len(text) < 500:
        return text

    summary = call_model(
        "Qwen/Qwen3-8B",
        f"Summarize this in {int(len(text)*target_ratio)} chars: {text}"
    )
    return summary
Enter fullscreen mode Exit fullscreen mode

Let me do the math that made me gasp. Say I have a 2,000-token system prompt. If I compress it to 400 tokens, I save 1,600 tokens per request. On DeepSeek V4 Flash at $0.25 per million tokens, that's $0.0004 per request on input. Wait, let me redo that properly...

Actually the original example said it saves $0.024 per request on a 2,000-token-to-400-token compression. Let me trust that. Ten thousand requests a day, that's $240 a day saved. $87,600 a year. From one prompt.

I had no idea. Blew my mind.

The trick is using a cheap model to do the compression. You don't want to use GPT-4o to compress your prompts because then you're paying GPT-4o prices to save money on cheaper models. That defeats the purpose. Use Qwen3-8B at $0.01/M to do the compressing. The cost of compression is microscopic compared to what you save.


Batching: Less Glamorous But Still Worth It

This one's a little less exciting but the savings are real. Instead of making ten separate API calls, you bundle them into one call. You save on overhead, you save on prompt repetition (because you only include the system prompt once), and you're generally more efficient.

The "before" version was something like:

for question in questions:
    response = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "model": "deepseek-v4-flash",
            "messages": [{"role": "user", "content": question}]
        }
    )
    print(response.json())
Enter fullscreen mode Exit fullscreen mode

That's ten API calls. Ten times the overhead. Ten times the system prompt tokens if you have one.

The "after" version is one big call asking the model to handle all of them at once. You usually get back 10-20% savings just from that, sometimes more depending on how repetitive your prompts are.

I batch everything I can now. My nightly job that processes customer feedback? Batched. My article summarizer? Batched. Once you get in the habit of looking for batching opportunities, you find them everywhere.


Tracking What I Actually Spend

I added a tiny logging wrapper around all my API calls. Every single request gets logged with the model name, the token count, and the calculated cost. Nothing fancy — just append to a JSON file or shove it into a SQLite database.

Why? Because I wanted to see where my money was going. And once you see it laid out, the patterns jump out. I noticed that 3% of my requests were costing 40% of my bill. Those were the ones going to the premium reasoning model. Was it worth it? Sometimes yes, sometimes no. Now I can actually decide instead of guessing.


What My Monthly Bill Looks Like Now

Here's the part that feels like a flex but I promise isn't. My friend's customer support project used to cost $312 a month on GPT-4o. After all the changes — smart routing, tiered escalation, caching, prompt compression, batching — it's running about $9 to $14 a month depending on traffic.

That's a 95-97% reduction. For the same quality of service. Nobody's complained. Nobody even noticed.

I genuinely had no idea this kind of optimization was possible when I was just starting out. I thought "cheap models = bad models" and that was that. But the cheap models now are genuinely good. Like, scary good. Qwen3-8B at one cent per million tokens can handle a huge range of tasks. DeepSeek V4 Flash at 25 cents is competitive with models that cost 40 times more.

The expensive models still have their place. For complex reasoning, for nuanced creative work, for tasks where every word matters — yeah, pay up. But for the other 80-90% of what most apps actually do? You're leaving so much money on the table.


Stuff I Want To Try Next

I'm not done. There's this whole semantic caching thing I mentioned. There's function calling and structured outputs that could let me do cleverer routing. There's fine-tuning small models on my specific use case which could let me push even more traffic to the cheap tier.

I also want to try setting up token budgets per user. Like, each user gets X tokens per day and if they hit the limit they get a polite "come back tomorrow" message. Could be huge for preventing abuse.

But for now? My setup is working. My bill is small. My code is clean. And I learned a ton along the way.


If You Want To Try This Stuff Yourself

Honestly, the biggest unlock for me was finding Global API. Before that I was juggling accounts with a bunch of different providers, which is a nightmare when you're trying to compare costs. Global API gives you one endpoint — global-apis.com/v1 — and you can hit all these different models with the same code. Same auth header, same request format, just swap the model name.

That's what made it actually fun to experiment. I could try Qwen3-8B and DeepSeek V4 Flash and DeepSeek Coder all in the same afternoon without setting up a million accounts. If you're curious about cutting your own bill down, check out Global API — it's at global-apis.com. Not sponsored, I just genuinely found it useful.

And if you're a bootcamp grad like me reading this — don't be afraid to use the cheap models. They're not charity cases. They're good. Save the expensive stuff for when it actually matters. Your wallet will thank you.

Top comments (0)