<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Asad Ibrahim</title>
    <description>The latest articles on DEV Community by Asad Ibrahim (@asad_ibrahim_9857456f842a).</description>
    <link>https://dev.to/asad_ibrahim_9857456f842a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4071010%2Fbfa047dd-12c2-4978-a3f6-ccc5b456a340.png</url>
      <title>DEV Community: Asad Ibrahim</title>
      <link>https://dev.to/asad_ibrahim_9857456f842a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asad_ibrahim_9857456f842a"/>
    <language>en</language>
    <item>
      <title>How I Cut My Voice Agent’s Groq API Usage by ~70% Without Changing the Model</title>
      <dc:creator>Asad Ibrahim</dc:creator>
      <pubDate>Mon, 10 Aug 2026 09:41:11 +0000</pubDate>
      <link>https://dev.to/asad_ibrahim_9857456f842a/how-i-cut-my-voice-agents-groq-api-usage-by-70-without-changing-the-model-40e9</link>
      <guid>https://dev.to/asad_ibrahim_9857456f842a/how-i-cut-my-voice-agents-groq-api-usage-by-70-without-changing-the-model-40e9</guid>
      <description>&lt;p&gt;A few weeks ago, I added a small AI voice assistant called Jarvis to my portfolio website.&lt;/p&gt;

&lt;p&gt;The setup was intentionally simple: Groq handled text generation, while the browser’s Web Speech API handled speech-to-text and text-to-speech. Visitors could ask Jarvis about my work, projects, experience, or services, and it could also help them book a call.&lt;/p&gt;

&lt;p&gt;It worked.&lt;/p&gt;

&lt;p&gt;There was just one problem.&lt;/p&gt;

&lt;p&gt;After about five minutes of fairly light testing, I had already burned through the Groq free-tier limit.&lt;/p&gt;

&lt;p&gt;My first thought was probably the obvious one:&lt;/p&gt;

&lt;p&gt;Do I need another provider or a paid API plan?&lt;/p&gt;

&lt;p&gt;Before changing anything, though, I decided to figure out where the tokens were actually going.&lt;/p&gt;

&lt;p&gt;That turned out to be the right decision.&lt;/p&gt;

&lt;p&gt;3,113 Prompt Tokens Just to Say “Hello”&lt;/p&gt;

&lt;p&gt;The first thing I wanted was an actual measurement.&lt;/p&gt;

&lt;p&gt;Instead of relying only on a token-counting estimate, I made a real Groq request with a minimal output limit and inspected the token usage returned by the API.&lt;/p&gt;

&lt;p&gt;Then I sent:&lt;/p&gt;

&lt;p&gt;hello&lt;/p&gt;

&lt;p&gt;The result surprised me:&lt;/p&gt;

&lt;p&gt;3,113 prompt tokens.&lt;/p&gt;

&lt;p&gt;Not for a complicated question.&lt;/p&gt;

&lt;p&gt;Not for a request involving several projects.&lt;/p&gt;

&lt;p&gt;Just “hello.”&lt;/p&gt;

&lt;p&gt;At that point, the problem became pretty obvious.&lt;/p&gt;

&lt;p&gt;My model wasn't necessarily expensive.&lt;/p&gt;

&lt;p&gt;My request architecture was.&lt;/p&gt;

&lt;p&gt;I found two major problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I was sending my entire portfolio every time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My system prompt contained almost everything about me:&lt;/p&gt;

&lt;p&gt;services&lt;br&gt;
project descriptions&lt;br&gt;
testimonials&lt;br&gt;
FAQs&lt;br&gt;
statistics&lt;br&gt;
tech stack&lt;br&gt;
experience&lt;br&gt;
behavioral instructions&lt;/p&gt;

&lt;p&gt;And all of it was being sent on every request, regardless of what the visitor asked.&lt;/p&gt;

&lt;p&gt;Someone saying “Hi” was effectively sending thousands of tokens of portfolio context to the model.&lt;/p&gt;

&lt;p&gt;Someone asking about pricing received the same context.&lt;/p&gt;

&lt;p&gt;Someone asking about one project also received information about every other project.&lt;/p&gt;

&lt;p&gt;It worked, but it was incredibly wasteful.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I had duplicated part of my knowledge base&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While auditing the knowledge object, I found something even simpler.&lt;/p&gt;

&lt;p&gt;My tech stack existed twice under two different fields.&lt;/p&gt;

&lt;p&gt;Two parts of the system had been built separately, and both included the same information without me noticing.&lt;/p&gt;

&lt;p&gt;So I wasn't just sending too much context.&lt;/p&gt;

&lt;p&gt;I was literally paying in tokens to send some of it twice.&lt;/p&gt;

&lt;p&gt;The Bigger Realization: Not Every Message Needs AI&lt;/p&gt;

&lt;p&gt;This ended up being the most important change.&lt;/p&gt;

&lt;p&gt;I had originally treated Jarvis like this:&lt;/p&gt;

&lt;p&gt;User message → Groq → response&lt;/p&gt;

&lt;p&gt;Every message went through the model.&lt;/p&gt;

&lt;p&gt;But why should an LLM generate an answer to:&lt;/p&gt;

&lt;p&gt;Hello&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;Who are you?&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;Do you sign NDAs?&lt;/p&gt;

&lt;p&gt;Those answers are already known.&lt;/p&gt;

&lt;p&gt;So I added a lightweight local intent layer before Groq.&lt;/p&gt;

&lt;p&gt;Now the flow looks more like:&lt;/p&gt;

&lt;p&gt;User message → local intent check → Groq only when necessary&lt;/p&gt;

&lt;p&gt;Simple regex and keyword matching handles predictable requests locally.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Greetings → predefined greeting&lt;br&gt;
“Who are you?” → fixed identity response&lt;br&gt;
Pricing questions → predefined pricing-policy response&lt;br&gt;
Known FAQs → existing FAQ answer&lt;br&gt;
Requests for private information → fixed refusal&lt;br&gt;
Obvious prompt-injection attempts → fixed security response&lt;/p&gt;

&lt;p&gt;If the intent matches one of these cases, Groq is never called.&lt;/p&gt;

&lt;p&gt;API usage for that interaction: zero.&lt;/p&gt;

&lt;p&gt;This also made the assistant feel faster because there is no reason to wait for model inference when the application already knows the answer.&lt;/p&gt;

&lt;p&gt;Then I Shrunk the System Prompt&lt;/p&gt;

&lt;p&gt;The next target was the prompt itself.&lt;/p&gt;

&lt;p&gt;Instead of shipping my entire portfolio with every request, I separated the prompt into two layers.&lt;/p&gt;

&lt;p&gt;Layer 1: A small base prompt&lt;/p&gt;

&lt;p&gt;The base prompt contains only information Jarvis always needs:&lt;/p&gt;

&lt;p&gt;identity&lt;br&gt;
behavior&lt;br&gt;
privacy rules&lt;br&gt;
pricing policy&lt;br&gt;
important boundaries&lt;br&gt;
response style&lt;/p&gt;

&lt;p&gt;After cleaning it up, the base context dropped to roughly 652 tokens, compared with the 3,113-token request I measured earlier.&lt;/p&gt;

&lt;p&gt;Layer 2: Retrieve Only Relevant Portfolio Knowledge&lt;/p&gt;

&lt;p&gt;The rest of my portfolio became selectively retrieved context.&lt;/p&gt;

&lt;p&gt;I divided the knowledge into sections such as:&lt;/p&gt;

&lt;p&gt;services&lt;br&gt;
projects&lt;br&gt;
testimonials&lt;br&gt;
faqs&lt;br&gt;
contact&lt;br&gt;
stats&lt;/p&gt;

&lt;p&gt;Before calling Groq, the application checks the user's message and determines which sections are actually relevant.&lt;/p&gt;

&lt;p&gt;If someone asks:&lt;/p&gt;

&lt;p&gt;“What AI automation work have you done?”&lt;/p&gt;

&lt;p&gt;Jarvis might receive relevant services and AI project information.&lt;/p&gt;

&lt;p&gt;It doesn't need every testimonial, contact detail, FAQ, and unrelated project.&lt;/p&gt;

&lt;p&gt;Usually only 2–4 relevant sections are added to the prompt.&lt;/p&gt;

&lt;p&gt;It isn't a complicated vector database or a full RAG pipeline.&lt;/p&gt;

&lt;p&gt;For a portfolio this size, simple retrieval works perfectly well.&lt;/p&gt;

&lt;p&gt;And more importantly, it's cheap.&lt;/p&gt;

&lt;p&gt;I Also Found a Retry Problem&lt;/p&gt;

&lt;p&gt;There was another source of unnecessary requests that wasn't immediately obvious: retries.&lt;/p&gt;

&lt;p&gt;SDKs often retry certain failed requests automatically, including rate-limit errors.&lt;/p&gt;

&lt;p&gt;That's normally helpful.&lt;/p&gt;

&lt;p&gt;But when you're already hitting a quota limit, automatic retries can make the situation worse.&lt;/p&gt;

&lt;p&gt;A request fails with a 429.&lt;/p&gt;

&lt;p&gt;The client retries.&lt;/p&gt;

&lt;p&gt;It fails again.&lt;/p&gt;

&lt;p&gt;Another retry happens.&lt;/p&gt;

&lt;p&gt;From the application's point of view, the visitor sent one message.&lt;/p&gt;

&lt;p&gt;From the API's point of view, multiple attempts may have occurred.&lt;/p&gt;

&lt;p&gt;So I tightened the retry behavior and added request-level protection around the voice agent.&lt;/p&gt;

&lt;p&gt;The final flow includes:&lt;/p&gt;

&lt;p&gt;request deduplication&lt;br&gt;
cooldown protection&lt;br&gt;
aborting superseded requests&lt;br&gt;
controlled retries&lt;br&gt;
request tracking&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;One visitor message should result in at most one intentional Groq generation request.&lt;/p&gt;

&lt;p&gt;The Result&lt;/p&gt;

&lt;p&gt;After the changes, the difference was significant.&lt;/p&gt;

&lt;p&gt;Before&lt;/p&gt;

&lt;p&gt;Measured “hello” request:&lt;/p&gt;

&lt;p&gt;3,113 prompt tokens&lt;/p&gt;

&lt;p&gt;After&lt;/p&gt;

&lt;p&gt;Compact base context:&lt;/p&gt;

&lt;p&gt;~652 tokens&lt;/p&gt;

&lt;p&gt;For requests that still need Groq, selective knowledge retrieval reduced prompt-token usage by roughly:&lt;/p&gt;

&lt;p&gt;70–72% in my testing.&lt;/p&gt;

&lt;p&gt;And several common interactions now use zero Groq requests:&lt;/p&gt;

&lt;p&gt;greetings&lt;br&gt;
identity questions&lt;br&gt;
pricing-policy questions&lt;br&gt;
known FAQs&lt;br&gt;
security refusals&lt;br&gt;
obvious prompt-injection attempts&lt;br&gt;
duplicate submissions&lt;/p&gt;

&lt;p&gt;The interesting part is that I didn't switch models.&lt;/p&gt;

&lt;p&gt;I didn't move to another AI provider.&lt;/p&gt;

&lt;p&gt;And I didn't solve the problem by simply paying for a larger quota.&lt;/p&gt;

&lt;p&gt;I changed how my application used the model.&lt;/p&gt;

&lt;p&gt;What I Learned&lt;/p&gt;

&lt;p&gt;When an AI application starts burning through API quota, it's easy to assume the model or provider is the problem.&lt;/p&gt;

&lt;p&gt;Sometimes it is.&lt;/p&gt;

&lt;p&gt;But before switching providers, I think it's worth looking at the request path itself.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;p&gt;Does this request actually need an LLM?&lt;/p&gt;

&lt;p&gt;Am I sending context the model doesn't need?&lt;/p&gt;

&lt;p&gt;Am I sending the same information repeatedly?&lt;/p&gt;

&lt;p&gt;Can part of this response be deterministic?&lt;/p&gt;

&lt;p&gt;Can I retrieve only the knowledge relevant to this question?&lt;/p&gt;

&lt;p&gt;Can one user action accidentally trigger multiple API requests?&lt;/p&gt;

&lt;p&gt;In my case, those questions mattered far more than changing the model.&lt;/p&gt;

&lt;p&gt;The biggest optimization wasn't finding a cheaper LLM.&lt;/p&gt;

&lt;p&gt;It was calling the LLM less often and sending it less unnecessary information when I did.&lt;/p&gt;

&lt;p&gt;I'm Asad Ibrahim, a full-stack developer and AI integration engineer. I build AI-powered web applications, automation systems, voice assistants, and production integrations for businesses.&lt;/p&gt;

&lt;p&gt;I also document experiments like this from projects I'm actually building.&lt;/p&gt;

&lt;p&gt;You can see more of my work, AI projects, and engineering case studies at asadibrahim.com.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>api</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
