<?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: Muiz</title>
    <description>The latest articles on DEV Community by Muiz (@muizidn).</description>
    <link>https://dev.to/muizidn</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%2F1115023%2F7cd4c537-8ba6-4795-abd5-1e3de7e4d057.jpeg</url>
      <title>DEV Community: Muiz</title>
      <link>https://dev.to/muizidn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muizidn"/>
    <language>en</language>
    <item>
      <title>Every API endpoint returned 500 errors. The logs revealed two MongoDB issues I wasn't expecting.</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 20 Jul 2026 04:40:34 +0000</pubDate>
      <link>https://dev.to/muizidn/every-api-endpoint-returned-500-errors-the-logs-revealed-two-mongodb-issues-i-wasnt-expecting-1242</link>
      <guid>https://dev.to/muizidn/every-api-endpoint-returned-500-errors-the-logs-revealed-two-mongodb-issues-i-wasnt-expecting-1242</guid>
      <description>&lt;p&gt;Today started with a nightmare scenario for any backend developer.&lt;/p&gt;

&lt;p&gt;Every API endpoint in my application suddenly started returning &lt;strong&gt;500 Internal Server Errors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6ahfxb82k1st5y0tq7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6ahfxb82k1st5y0tq7f.png" alt="list of errors endpoints" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, I assumed it was something I had recently deployed. I reviewed the latest commits, checked the deployment pipeline, verified environment variables, and inspected application logs.&lt;/p&gt;

&lt;p&gt;Nothing obvious stood out.&lt;/p&gt;

&lt;p&gt;Then I enter the VPS. Check the docker logs.&lt;/p&gt;

&lt;p&gt;I noticed repeated MongoDB errors appearing throughout the logs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6k17x3tmzrks19gmi81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6k17x3tmzrks19gmi81.png" alt="logs from docker" width="800" height="504"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNSException: querySrv ESERVFAIL
_mongodb._tcp.cluster0.mongodb.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Naturally, I thought the outage was caused by a MongoDB connectivity issue. The symptoms matched perfectly: database failures, followed by API failures.&lt;/p&gt;

&lt;p&gt;But after digging deeper, another error kept showing up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MongoServerError: Index build failed

E11000 duplicate key error
collection: roles
index: id_1
dup key: { id: null }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This turned out to be the real clue.&lt;/p&gt;

&lt;p&gt;MongoDB was attempting to build a unique index on the &lt;code&gt;id&lt;/code&gt; field, but multiple documents already existed with &lt;code&gt;id: null&lt;/code&gt;. The index build failed, which caused repository initialization issues and eventually surfaced as 500 errors across the application.&lt;/p&gt;

&lt;p&gt;What made this incident interesting was how misleading the symptoms were.&lt;/p&gt;

&lt;p&gt;The API looked broken.&lt;/p&gt;

&lt;p&gt;The database connection looked broken.&lt;/p&gt;

&lt;p&gt;But the actual root cause was a data integrity issue hiding inside the collection.&lt;/p&gt;

&lt;p&gt;A few reminders I took away from today's debugging session:&lt;/p&gt;

&lt;p&gt;✅ When every endpoint fails, look for shared dependencies.&lt;/p&gt;

&lt;p&gt;✅ The first error you see isn't always the root cause.&lt;/p&gt;

&lt;p&gt;✅ Database indexes deserve the same attention as application code.&lt;/p&gt;

&lt;p&gt;✅ A single bad document can trigger failures across an entire system.&lt;/p&gt;

&lt;p&gt;Debugging distributed systems is often less about fixing code and more about following evidence until the story finally makes sense.&lt;/p&gt;

&lt;p&gt;Today, that story ended with a duplicate MongoDB index failure hiding behind a wall of 500 errors.&lt;/p&gt;

&lt;p&gt;While debugging this from the frontend side, I used a tool I built for inspecting network traffic Network Spy, which helped me trace the root cause faster: &lt;a href="https://networkspy.app/?utm_source=dev.to&amp;amp;utm_medium=blog&amp;amp;utm_campaign=network_spy"&gt;Check it here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
    </item>
    <item>
      <title>AI can make developers faster — and also dangerously less observant</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 20 Jul 2026 04:40:11 +0000</pubDate>
      <link>https://dev.to/muizidn/ai-can-make-developers-faster-and-also-dangerously-less-observant-4f18</link>
      <guid>https://dev.to/muizidn/ai-can-make-developers-faster-and-also-dangerously-less-observant-4f18</guid>
      <description>&lt;p&gt;I have a project that is (debatably, like any real-world system) well-structured and follows solid engineering practices. Clear separation of concerns, proper build pipeline, and strict rules around what should and shouldn’t be committed.&lt;/p&gt;

&lt;p&gt;A new developer joins the project.&lt;br&gt;
They are eager. Productive. And like many developers today, they have AI tools like Claude Code in their workflow.&lt;/p&gt;

&lt;p&gt;At first, everything looks fine.&lt;/p&gt;

&lt;p&gt;Code is being written fast. Features are landing quickly. The velocity looks great.&lt;/p&gt;

&lt;p&gt;Then I start noticing something small — but important.&lt;/p&gt;

&lt;p&gt;Version-controlled files begin including artifacts like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;storybook-static/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;build outputs&lt;/li&gt;
&lt;li&gt;generated files that should never be committed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;

&lt;p&gt;Because the system already defines what should and shouldn’t be tracked in Git. There are rules, &lt;code&gt;.gitignore&lt;/code&gt;, and established conventions.&lt;/p&gt;

&lt;p&gt;So the real question becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why wasn’t this the first thing caught before committing?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The shift I’ve noticed with AI-assisted development
&lt;/h2&gt;

&lt;p&gt;From what I observe, tools like Claude Code, Copilot, or agent-based workflows change the development pattern:&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;write code → think → review → commit&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ask AI → accept output → commit → move on&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And if you're not careful, one subtle behavior emerges:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It works, so I ship it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But “it works” is not the same as “it’s correct for the system.”&lt;/p&gt;




&lt;h2&gt;
  
  
  A real workflow gap
&lt;/h2&gt;

&lt;p&gt;In my own experience using tools like Opencode, I noticed a pattern:&lt;/p&gt;

&lt;p&gt;Once I ask it to commit, the next instruction often becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;just commit everything that changed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is extremely powerful — but also dangerous.&lt;/p&gt;

&lt;p&gt;Because it subtly removes a critical step:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;human verification of what is actually being committed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that’s exactly where things like build artifacts, debug files, or unintended changes slip in.&lt;/p&gt;

&lt;p&gt;Not because the AI is wrong —&lt;br&gt;
but because the human stopped reviewing deeply.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem isn’t AI
&lt;/h2&gt;

&lt;p&gt;AI is not the issue.&lt;/p&gt;

&lt;p&gt;The issue is &lt;strong&gt;delegated responsibility without retained awareness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When developers start trusting AI outputs blindly, the workflow shifts from engineering to execution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI writes&lt;/li&gt;
&lt;li&gt;AI prepares commit&lt;/li&gt;
&lt;li&gt;AI suggests changes&lt;/li&gt;
&lt;li&gt;Human approves without deep inspection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where subtle but serious mistakes start appearing in production systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this teaches me
&lt;/h2&gt;

&lt;p&gt;This experience reinforced a few important principles:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Review and re-review
&lt;/h3&gt;

&lt;p&gt;Every commit matters — even if it was generated by AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Always be the second pair of eyes
&lt;/h3&gt;

&lt;p&gt;AI can be the first author.&lt;br&gt;
You must always be the reviewer.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. You are still the engineer
&lt;/h3&gt;

&lt;p&gt;AI gives you speed, not judgment.&lt;/p&gt;

&lt;p&gt;You might now have “100 hands” to write code —&lt;br&gt;
but that doesn’t mean you stop thinking.&lt;/p&gt;

&lt;p&gt;If anything, you need to think more, not less.&lt;/p&gt;




&lt;h2&gt;
  
  
  The uncomfortable truth about “vibe coding”
&lt;/h2&gt;

&lt;p&gt;This is also why many “vibe-coded” applications look fine at first — but slowly accumulate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;security issues&lt;/li&gt;
&lt;li&gt;misconfigurations&lt;/li&gt;
&lt;li&gt;leaked build artifacts&lt;/li&gt;
&lt;li&gt;inconsistent architecture decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not because developers are incapable.&lt;/p&gt;

&lt;p&gt;But because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;they stop inspecting what they didn’t personally write.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;AI didn’t make development worse.&lt;/p&gt;

&lt;p&gt;But it did change the failure mode:&lt;/p&gt;

&lt;p&gt;From:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I wrote bad code”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I didn’t review what was written”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that is a much harder problem to notice — until it reaches production.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Why I still don’t use Claude (and why a “cheap model” is enough for me)</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 20 Jul 2026 04:39:50 +0000</pubDate>
      <link>https://dev.to/muizidn/why-i-still-dont-use-claude-and-why-a-cheap-model-is-enough-for-me-37e8</link>
      <guid>https://dev.to/muizidn/why-i-still-dont-use-claude-and-why-a-cheap-model-is-enough-for-me-37e8</guid>
      <description>&lt;p&gt;In most discussions today, it feels like using advanced AI models has become a status signal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;higher usage, bigger bills, “Claude maxed out again”, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But my experience has been a bit different.&lt;/p&gt;

&lt;p&gt;I still primarily use a &lt;strong&gt;cheap model setup&lt;/strong&gt;, and it has been enough for my workflow.&lt;/p&gt;

&lt;p&gt;Here’s why.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. I still consider myself the engineer
&lt;/h2&gt;

&lt;p&gt;The core principle for me is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The model is a tool, not the engineer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As long as the model can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;follow instructions&lt;/li&gt;
&lt;li&gt;generate decent code&lt;/li&gt;
&lt;li&gt;respect constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then it’s usable.&lt;/p&gt;

&lt;p&gt;At the beginning, I mainly used ChatGPT web for coding because it was the most consistent option for instruction-following at the time.&lt;/p&gt;

&lt;p&gt;Other tools existed, but they weren’t reliable enough in structured tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Claude is good — but the limits are real
&lt;/h2&gt;

&lt;p&gt;Claude is genuinely strong in many cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;good reasoning&lt;/li&gt;
&lt;li&gt;clean code generation&lt;/li&gt;
&lt;li&gt;strong long-context understanding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in practice, there’s a constraint that matters a lot:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;usage limits.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And once you hit that limit mid-flow, your workflow gets interrupted.&lt;/p&gt;

&lt;p&gt;That alone changes how I evaluate tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Other models improved, but instruction-following is still inconsistent
&lt;/h2&gt;

&lt;p&gt;Over time, more models started appearing — including some cheaper or open alternatives.&lt;/p&gt;

&lt;p&gt;Some are fast. Some are cheap. Some are surprisingly capable.&lt;/p&gt;

&lt;p&gt;But I consistently noticed a pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They &lt;em&gt;say&lt;/em&gt; they will follow instructions&lt;/li&gt;
&lt;li&gt;But the actual output drifts&lt;/li&gt;
&lt;li&gt;They modify things I explicitly told them not to touch&lt;/li&gt;
&lt;li&gt;Tool usage is often simulated, not executed properly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That mismatch makes them harder to trust in structured engineering work.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The real requirement: predictable behavior
&lt;/h2&gt;

&lt;p&gt;For my workflow, I don’t need the “smartest” model.&lt;/p&gt;

&lt;p&gt;I need the &lt;strong&gt;most predictable one&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because I usually work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;well-defined architecture&lt;/li&gt;
&lt;li&gt;strict boundaries on what should change&lt;/li&gt;
&lt;li&gt;clearly scoped tasks&lt;/li&gt;
&lt;li&gt;explicit instructions on where NOT to modify anything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In that setup, consistency matters more than raw intelligence.&lt;/p&gt;

&lt;p&gt;Right now, tools like &lt;strong&gt;DeepSeek V4 / Flash via OpenCode&lt;/strong&gt; are “good enough” for that.&lt;/p&gt;

&lt;p&gt;They follow structure, respect context, and don’t overcomplicate changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Why I never “had to switch to Claude”
&lt;/h2&gt;

&lt;p&gt;I often see developers talking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hitting Claude limits&lt;/li&gt;
&lt;li&gt;paying high monthly bills&lt;/li&gt;
&lt;li&gt;relying heavily on Claude for everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in my case, I never reached that point.&lt;/p&gt;

&lt;p&gt;Not because Claude is bad — it’s not.&lt;/p&gt;

&lt;p&gt;But because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;my workflow is constrained enough that a cheaper model already satisfies the requirements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And when the problem is well-defined, you don’t always need the most powerful tool — just the most reliable one.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The trade-off people miss
&lt;/h2&gt;

&lt;p&gt;Yes, Claude can be better in many scenarios.&lt;/p&gt;

&lt;p&gt;But the trade-off is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better reasoning → higher cost + limits&lt;/li&gt;
&lt;li&gt;Good enough reasoning → stable + cheap + continuous usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for engineering work, continuity often wins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;I don’t avoid Claude because it’s bad.&lt;/p&gt;

&lt;p&gt;I avoid it because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;it is not the most cost-effective tool for the way I structure my work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the end of the day, I still believe this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best AI tool is the one that reliably follows your instructions — not the one that sounds the smartest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And so far, for my use case, a cheaper model has been more than enough.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>JSON API Response Design: Small Decisions That Save Months of Maintenance</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 20 Jul 2026 04:38:53 +0000</pubDate>
      <link>https://dev.to/muizidn/json-api-response-design-small-decisions-that-save-months-of-maintenance-5g2e</link>
      <guid>https://dev.to/muizidn/json-api-response-design-small-decisions-that-save-months-of-maintenance-5g2e</guid>
      <description>&lt;p&gt;Most developers spend a lot of time designing databases, infrastructure, and application architecture.&lt;/p&gt;

&lt;p&gt;But surprisingly little time is spent designing something every client consumes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The API response format.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A poorly designed response structure creates confusion, duplicate code, inconsistent error handling, and unnecessary bugs across frontend, mobile, backend, and QA teams.&lt;/p&gt;

&lt;p&gt;Let's explore a practical approach to JSON API response design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Many APIs start like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Seems fine.&lt;/p&gt;

&lt;p&gt;Until an error occurs:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then another endpoint returns:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invalid token"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And another one returns:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Permission denied"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now every consumer needs special handling for every endpoint.&lt;/p&gt;

&lt;p&gt;As the API grows, the problem grows with it.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Consistent Response Envelope
&lt;/h2&gt;

&lt;p&gt;A common pattern is using a standard wrapper around all responses.&lt;/p&gt;

&lt;p&gt;Success:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Failure:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This gives clients a predictable structure regardless of the endpoint.&lt;/p&gt;


&lt;h2&gt;
  
  
  Include Machine-Readable Error Codes
&lt;/h2&gt;

&lt;p&gt;Avoid relying solely on error messages.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EMAIL_ALREADY_EXISTS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Email already exists"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Frontend applications can now implement logic using the code instead of parsing text.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EMAIL_ALREADY_EXISTS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;showEmailError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Messages may change.&lt;/p&gt;

&lt;p&gt;Codes should not.&lt;/p&gt;


&lt;h2&gt;
  
  
  Return Metadata Separately
&lt;/h2&gt;

&lt;p&gt;Avoid mixing business data with metadata.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This becomes especially useful when implementing pagination, filtering, sorting, and analytics.&lt;/p&gt;


&lt;h2&gt;
  
  
  Timestamps Should Be ISO 8601
&lt;/h2&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"06/21/2026 14:30"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Good:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-21T14:30:00Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;ISO 8601 avoids timezone confusion and is supported by nearly every platform.&lt;/p&gt;


&lt;h2&gt;
  
  
  Avoid Null When Possible
&lt;/h2&gt;

&lt;p&gt;Many APIs return:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now clients must handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;null&lt;/li&gt;
&lt;li&gt;undefined&lt;/li&gt;
&lt;li&gt;empty array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;An empty collection is often easier to reason about than a nullable collection.&lt;/p&gt;


&lt;h2&gt;
  
  
  Pagination Should Be Explicit
&lt;/h2&gt;

&lt;p&gt;A paginated response should provide enough information for clients to continue fetching.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"has_next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or cursor-based pagination:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_cursor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJpZCI6MTIzfQ=="&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This avoids guesswork on the client side.&lt;/p&gt;


&lt;h2&gt;
  
  
  Don't Leak Internal Errors
&lt;/h2&gt;

&lt;p&gt;Never expose raw stack traces.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SQLSTATE[23000]: Integrity constraint violation..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INTERNAL_SERVER_ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Something went wrong"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Log details internally.&lt;/p&gt;

&lt;p&gt;Return safe information externally.&lt;/p&gt;


&lt;h2&gt;
  
  
  Versioning Matters
&lt;/h2&gt;

&lt;p&gt;APIs live longer than most developers expect.&lt;/p&gt;

&lt;p&gt;Instead of breaking existing clients:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v1/users
/api/v2/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: application/vnd.company.v2+json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A versioning strategy saves painful migrations later.&lt;/p&gt;


&lt;h2&gt;
  
  
  Example Final Response Format
&lt;/h2&gt;

&lt;p&gt;Success:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req_123456"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Error:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User not found"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req_123456"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice the &lt;code&gt;request_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When a customer reports an issue, support can immediately locate the exact request in logs.&lt;/p&gt;


&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;A good API response format is not about aesthetics.&lt;/p&gt;

&lt;p&gt;It is about reducing complexity across every consumer of the API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend applications&lt;/li&gt;
&lt;li&gt;Mobile applications&lt;/li&gt;
&lt;li&gt;QA automation&lt;/li&gt;
&lt;li&gt;Integrations&lt;/li&gt;
&lt;li&gt;AI agents&lt;/li&gt;
&lt;li&gt;Future developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best API responses are boring, predictable, and easy to reason about.&lt;/p&gt;

&lt;p&gt;Your future teammates will thank you for it.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; When designing or debugging APIs, inspect the actual HTTP traffic instead of relying only on application logs. Seeing the raw request and response often reveals inconsistencies, missing fields, incorrect status codes, and serialization issues much faster.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://networkspy.app/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnetworkspy.app%2Fog-home.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://networkspy.app/" rel="noopener noreferrer" class="c-link"&gt;
            HTTP Traffic Debugger for AI powered teams | NetworkSpy
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Inspect, debug, and understand modern API traffic with NetworkSpy, the network debugger built for GraphQL, streaming, and AI applications.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnetworkspy.app%2Ffavicon%2Ffavicon-32x32.png" width="32" height="32"&gt;
          networkspy.app
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>json</category>
      <category>restapi</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Debounce Isn't Just About Performance—It's About Being Nice to Your API</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 20 Jul 2026 04:34:46 +0000</pubDate>
      <link>https://dev.to/muizidn/debounce-isnt-just-about-performance-its-about-being-nice-to-your-api-ba2</link>
      <guid>https://dev.to/muizidn/debounce-isnt-just-about-performance-its-about-being-nice-to-your-api-ba2</guid>
      <description>&lt;p&gt;Every developer has written something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;Until someone starts typing.&lt;/p&gt;

&lt;p&gt;If the user types &lt;strong&gt;"Hello"&lt;/strong&gt;, your application sends five requests:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H      → request
He     → request
Hel    → request
Hell   → request
Hello  → request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For a single search.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why this is a problem
&lt;/h2&gt;

&lt;p&gt;Five unnecessary requests might not sound like much.&lt;/p&gt;

&lt;p&gt;Now imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,000 active users&lt;/li&gt;
&lt;li&gt;Search suggestions&lt;/li&gt;
&lt;li&gt;AI autocomplete&lt;/li&gt;
&lt;li&gt;Product search&lt;/li&gt;
&lt;li&gt;Database queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your backend suddenly receives thousands of requests that nobody actually wanted.&lt;/p&gt;

&lt;p&gt;Most of them become obsolete the moment the next character is typed.&lt;/p&gt;

&lt;p&gt;You're spending CPU time, bandwidth, and database resources on results the user will never see.&lt;/p&gt;


&lt;h2&gt;
  
  
  The solution: Debounce
&lt;/h2&gt;

&lt;p&gt;Instead of calling your function immediately, wait until the user pauses typing.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;debouncedSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;debouncedSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now the interaction becomes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H
He
Hel
Hell
Hello
      │
   wait 300ms
      │
      ▼
search("Hello")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Only one request is sent.&lt;/p&gt;


&lt;h2&gt;
  
  
  Better UX too
&lt;/h2&gt;

&lt;p&gt;Debouncing doesn't just help your servers.&lt;/p&gt;

&lt;p&gt;It also creates a smoother experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less UI flickering&lt;/li&gt;
&lt;li&gt;Fewer loading indicators&lt;/li&gt;
&lt;li&gt;Fewer race conditions&lt;/li&gt;
&lt;li&gt;Less chance that older responses overwrite newer ones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your application feels calmer and more responsive.&lt;/p&gt;


&lt;h2&gt;
  
  
  Verify that it actually works
&lt;/h2&gt;

&lt;p&gt;Don't assume your debounce implementation is correct.&lt;/p&gt;

&lt;p&gt;Open your browser, type quickly into your search box, and inspect the network traffic.&lt;/p&gt;

&lt;p&gt;Without debounce, you'll see a request for nearly every keystroke.&lt;/p&gt;

&lt;p&gt;With debounce, you should see a single request after the user pauses typing.&lt;/p&gt;

&lt;p&gt;This simple check can reveal accidental bugs, duplicate requests, or places where debounce isn't applied consistently.&lt;/p&gt;


&lt;h2&gt;
  
  
  One more thing
&lt;/h2&gt;

&lt;p&gt;Debounce reduces how often requests are &lt;strong&gt;started&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It doesn't cancel requests that have already been sent.&lt;/p&gt;

&lt;p&gt;If your application fires long-running network requests, combine debounce with request cancellation using &lt;code&gt;AbortController&lt;/code&gt; or &lt;code&gt;AbortSignal&lt;/code&gt; so outdated requests don't continue consuming resources.&lt;/p&gt;

&lt;p&gt;The combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debounce&lt;/li&gt;
&lt;li&gt;Request cancellation&lt;/li&gt;
&lt;li&gt;Timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;results in a faster UI and a healthier backend.&lt;/p&gt;


&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Every unnecessary request has a cost.&lt;/p&gt;

&lt;p&gt;It consumes bandwidth.&lt;br&gt;
It increases server load.&lt;br&gt;
It slows databases.&lt;br&gt;
It wastes money.&lt;/p&gt;

&lt;p&gt;A few hundred milliseconds of patience can save thousands of unnecessary API calls every day.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; If you want to confirm your debounce implementation is actually working, inspect your HTTP traffic with &lt;strong&gt;NetworkSpy&lt;/strong&gt;. Watching the requests in real time makes it easy to spot duplicate calls and ensure you're not putting unnecessary pressure on your API.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://networkspy.app/httptoolkit-alternative" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnetworkspy.app%2Fog-home.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://networkspy.app/httptoolkit-alternative" rel="noopener noreferrer" class="c-link"&gt;
            A Faster HTTP Toolkit Alternative for Modern API Teams | NetworkSpy
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            HTTP Toolkit is approachable for web debugging, but modern API teams often need deeper visibility into streaming responses, GraphQL payloads, mobile traffic, and high-volume local workflows. NetworkSpy gives you a fast cross-platform workspace for inspecting, comparing, and understanding complex API behavior.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnetworkspy.app%2Ffavicon%2Ffavicon-32x32.png"&gt;
          networkspy.app
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>restapi</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Learning HTTP, HTTPS, TLS, and SSL is dauting. Yet I should learn it because its part of the job and I should explain to people.

Give me list of good resources to learn!</title>
      <dc:creator>Muiz</dc:creator>
      <pubDate>Mon, 04 May 2026 23:50:34 +0000</pubDate>
      <link>https://dev.to/muizidn/learning-http-https-tls-and-ssl-is-dauting-yet-i-should-learn-it-because-its-part-of-the-job-1446</link>
      <guid>https://dev.to/muizidn/learning-http-https-tls-and-ssl-is-dauting-yet-i-should-learn-it-because-its-part-of-the-job-1446</guid>
      <description></description>
      <category>learning</category>
      <category>networking</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
