<?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: Ajitkumar Singh</title>
    <description>The latest articles on DEV Community by Ajitkumar Singh (@ajitkumar_singh_7a94b3eaa).</description>
    <link>https://dev.to/ajitkumar_singh_7a94b3eaa</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%2F4173647%2F2d9a099b-f36d-4162-ac08-7019829b5e27.png</url>
      <title>DEV Community: Ajitkumar Singh</title>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ajitkumar_singh_7a94b3eaa"/>
    <language>en</language>
    <item>
      <title>Five ways to code with AI, five different risks</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Fri, 30 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/five-ways-to-code-with-ai-five-different-risks-4hi6</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/five-ways-to-code-with-ai-five-different-risks-4hi6</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6draw6bc7nchxqf87zw5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6draw6bc7nchxqf87zw5.png" alt="Table of five AI coding modes. Completion: text suggestion only, risk of a plausible local error. Chat assistant: usually read-only, risk of missing repo context. Interactive agent: files and chosen commands, risk of a wrong multi-file edit. Async agent: throwaway environment and branch, risk of unsupervised drift. Agentic workflow: policy-run automation, risk of a bad rule at scale." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"We use AI for coding" covers at least five different arrangements, and they fail in different ways. Before picking one, it helps to be precise about what a coding agent is.&lt;/p&gt;

&lt;p&gt;A coding agent is a software system that uses a generative model to choose and sequence repository tools toward an engineering goal, while an external runtime controls what it can see, change, run and report. The model proposes. The harness supplies files, search, shell commands and patches. Policies decide whether an action is allowed. Tests and reviewers decide whether the result is acceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five modes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Unit of work&lt;/th&gt;
&lt;th&gt;Typical authority&lt;/th&gt;
&lt;th&gt;Main risk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Completion&lt;/td&gt;
&lt;td&gt;the next tokens or line&lt;/td&gt;
&lt;td&gt;a text suggestion only&lt;/td&gt;
&lt;td&gt;a plausible local error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat assistant&lt;/td&gt;
&lt;td&gt;an explanation or snippet&lt;/td&gt;
&lt;td&gt;usually read-only&lt;/td&gt;
&lt;td&gt;missing repository context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interactive coding agent&lt;/td&gt;
&lt;td&gt;a bounded repository change&lt;/td&gt;
&lt;td&gt;files and selected commands&lt;/td&gt;
&lt;td&gt;an incorrect multi-file change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asynchronous coding agent&lt;/td&gt;
&lt;td&gt;an issue, pull request or maintenance job&lt;/td&gt;
&lt;td&gt;a disposable environment and branch&lt;/td&gt;
&lt;td&gt;unsupervised drift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agentic workflow&lt;/td&gt;
&lt;td&gt;a repeatable delivery process&lt;/td&gt;
&lt;td&gt;policy-controlled automation&lt;/td&gt;
&lt;td&gt;a bad rule applied at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Not a maturity ladder
&lt;/h2&gt;

&lt;p&gt;It is tempting to read the table top to bottom as a path from beginner to expert. It is not. A low-risk refactor across fifty files may suit an asynchronous agent that opens a pull request overnight. A production incident may call for an interactive agent with a senior engineer watching every step. The right mode follows from how reversible the change is, how uncertain the task is, and what a mistake would cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  One session, several systems
&lt;/h2&gt;

&lt;p&gt;Here is an interactive session from the course. A developer asks an agent to fix a duplicate payment retry. The model does not get the whole repository: the harness first gives it the project instructions and search tools. It searches for the timeout error, reads the retry policy and its integration test, and proposes a plan touching three files. Policy allows edits in the workspace and local tests, and denies network and secret access. The model patches the retry key, runs a focused test, hits a contract failure, inspects the checkout response type, revises the patch, and runs the wider payment suite. A human reviews the diff, and CI reruns every required check independently.&lt;/p&gt;

&lt;p&gt;Count the systems in that story: a model that proposes, a harness that executes, a sandbox that limits reach, a repository that holds local truth, a CI system that produces independent evidence, and a reviewer who grants authority.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Engineering Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Calling all of that "the AI" hides the boundaries engineers have to design. Most incidents with coding agents happen at one of those boundaries: a permission set too wide, a test that was not run, a review that was skipped.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/five-ways-to-code-with-ai?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/ai-coding-agents-for-professional-engineers.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#coding-agent" rel="noopener noreferrer"&gt;What a Coding Agent Actually Is&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>What multi-AZ buys, and what it doesn't</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Wed, 28 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/what-multi-az-buys-and-what-it-doesnt-3o7l</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/what-multi-az-buys-and-what-it-doesnt-3o7l</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8yfdnua7nxvmhfqqzzxs.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8yfdnua7nxvmhfqqzzxs.png" alt="A table of failures against what survives them. Power, cooling or fibre loss and a rack or host failure: multi-AZ yes, multi-region yes. A regional control-plane incident: multi-AZ no, multi-region yes if the standby needs no API calls in the failed region. A bad deployment, an expired certificate and a corrupt schema migration: no in both columns. An exhausted account quota: multi-AZ no, multi-region partly. Below: three zones survive losing one only if two can carry peak load, so run at or below 66% utilisation." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Region" and "availability zone" sound like marketing. They are really definitions of failure domains, and knowing exactly which failures each one contains is most of designing for them.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;region&lt;/strong&gt; is a geographic area with its own control plane, such as ap-south-1 in Mumbai or eu-west-1 in Ireland. Regions are almost completely independent: separate APIs, separate service endpoints, separate failure domains, and no data moves between them unless you move it.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;availability zone&lt;/strong&gt; is one or more data centres inside a region, with independent power, cooling and networking, linked to the other zones by low-latency connections of typically single-digit milliseconds. Zones fail independently, for physical reasons: a power event, a cooling failure, a fibre cut.&lt;/p&gt;

&lt;h2&gt;
  
  
  What each boundary covers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;Multi-AZ survives it&lt;/th&gt;
&lt;th&gt;Multi-region survives it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Power, cooling or fibre loss in one data centre&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A rack or host failure&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A regional control-plane incident&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes, if the standby needs no API calls in the failed region&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A bad deployment&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No, and active-active makes it worse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An expired certificate&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A corrupt schema migration&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No: replication faithfully copies the corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An exhausted account quota&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Partly, because quotas are per region&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three rows say no in both columns, and the quota row is covered only in part. A deployment pipeline crosses every zone and region without noticing them, the same certificate sits in every zone, and a corrupt migration replicates. Changes like these cause a large share of outages. Multi-AZ protects against infrastructure failure, multi-region against regional failure, and neither protects against you. A team asking for a third zone when its last four incidents were deploys is optimising the column that was already covered.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two boundaries cost different things
&lt;/h2&gt;

&lt;p&gt;Crossing a zone costs one to two milliseconds and a per-gigabyte charge on the traffic, which is small enough that spreading across zones should be the default for everything. Crossing a region costs tens to over a hundred milliseconds; Mumbai to Ireland is roughly 120 ms round trip. That is an architectural constraint rather than a line item. A synchronous cross-region call inside a request path spends more time on the wire than most services spend on their entire response, and no amount of tuning wins it back.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Mistake&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Calling a service multi-AZ because it runs in three zones. Lose one zone and capacity drops by a third; if the other two saturate, the service failed along with the zone. Surviving the loss of a third means serving peak load on the remaining two thirds, which means running at or below 66% utilisation at peak. A zone-removal drill tells you which kind of deployment you actually have.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/what-multi-az-buys?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/aws-architecture-for-backend-engineers.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#region-az" rel="noopener noreferrer"&gt;Regions, Zones, and What Multi-AZ Actually Buys&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>sre</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Same average, very different users</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Tue, 27 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/same-average-very-different-users-37n7</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/same-average-very-different-users-37n7</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9jaghdjwatz0dc81hdy.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9jaghdjwatz0dc81hdy.png" alt="Two latency panels with the same 153 ms mean. Service A: p50 153 ms, p99 161 ms, no requests over 1 second. Service B: p50 14 ms, p99 1,416 ms, 1,000 of 10,000 requests over 1 second." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two services each handle 10,000 requests. A latency dashboard that shows the mean reports the same number for both: 153.0 ms, identical to one decimal place. They are not the same service.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;p50&lt;/th&gt;
&lt;th&gt;p90&lt;/th&gt;
&lt;th&gt;p99&lt;/th&gt;
&lt;th&gt;Max&lt;/th&gt;
&lt;th&gt;Requests over 1 s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Service A, uniformly a little slow&lt;/td&gt;
&lt;td&gt;153.0 ms&lt;/td&gt;
&lt;td&gt;153.0 ms&lt;/td&gt;
&lt;td&gt;160.0 ms&lt;/td&gt;
&lt;td&gt;161.0 ms&lt;/td&gt;
&lt;td&gt;161.0 ms&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service B, fast with a 10% tail&lt;/td&gt;
&lt;td&gt;153.0 ms&lt;/td&gt;
&lt;td&gt;14.0 ms&lt;/td&gt;
&lt;td&gt;17.0 ms&lt;/td&gt;
&lt;td&gt;1,416.0 ms&lt;/td&gt;
&lt;td&gt;1,419.0 ms&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In service A, nobody waits more than 161 ms. In service B, a thousand people wait almost a second and a half.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mean is doing exactly its job
&lt;/h2&gt;

&lt;p&gt;A mean measures central tendency. It is deliberately insensitive to outliers, and in latency the outliers are the incident. Asking the mean to show a slow tail is asking it to do the one thing it was designed not to do.&lt;/p&gt;

&lt;p&gt;Two things make it worse in practice. First, the mean has no unit of experience: no user of service B ever waited 153 ms. Their requests took about 14 ms or about 1,400 ms, and the average describes a request that never happened.&lt;/p&gt;

&lt;p&gt;Second, the tail is not a small group of people. A p99 affects one request in a hundred, but a page or session that makes 100 requests is likely to hit it at least once: if each request independently has a 1% chance of landing in the tail, the chance is 1 ‚àí 0.99¬π‚Å∞‚Å∞, about 63%. Fan-out turns a rare request into a common experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch instead
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Percentiles per endpoint&lt;/strong&gt;: p50 for the typical request, p99 and the maximum for the people having a bad time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A count of requests over a threshold&lt;/strong&gt; you care about, such as one second. It reads like the table above, and it maps directly to an objective.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Histograms, aggregated across servers.&lt;/strong&gt; They can be merged; percentiles cannot.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Mistake&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Averaging each server's p99 to get a fleet-wide p99. Percentiles do not combine that way: the mean of eight servers' p99 values is not the p99 of all their requests. Merge the latency histograms first, then read the percentile from the result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The mean still has a use: it tracks total work and capacity. It just cannot tell you who is waiting.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/same-average-different-users?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/observability-and-production-engineering.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#averages" rel="noopener noreferrer"&gt;The Average Is the Statistic Designed Not to See This&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>observability</category>
      <category>sre</category>
      <category>monitoring</category>
      <category>performance</category>
    </item>
    <item>
      <title>Read an MCP server before you trust it</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Sun, 25 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/read-an-mcp-server-before-you-trust-it-4fpg</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/read-an-mcp-server-before-you-trust-it-4fpg</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4lmoxm5wh0oizltjh68.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4lmoxm5wh0oizltjh68.png" alt="Four steps for a new MCP server. 1, pin a version: tool descriptions are instructions a model reads, and an unpinned install fetches whatever was published last. 2, list what it offers with the Inspector's tools/list before any model can; the reference server exposes fourteen tools. 3, read the hints and doubt them: get-env is marked readOnlyHint true and returned DEMO_API_KEY; gzip-file-as-resource is marked openWorldHint true and fetches any URL from your machine, even 169.254.169.254. 4, allow only what you decided: a denied tool is removed from the model's context, and an allow list is safer because tools a later version adds stay off. Read-only describes side effects, not confidentiality." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The quickest way to learn what an MCP server owes its users is to be one first. The reference server that the MCP maintainers publish to exercise every protocol feature is a good place to start: it is safe to run, and it shows exactly why you read a server before you trust it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pin the version
&lt;/h2&gt;

&lt;p&gt;An MCP server's tool descriptions are instructions that a model reads. Start a server with &lt;code&gt;npx some-server&lt;/code&gt; and no version, and every start fetches whatever was published last, so a later release can change what those instructions say without you noticing. Pin an exact version, and a change reaches you only when you choose to upgrade and read what changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  List what it offers
&lt;/h2&gt;

&lt;p&gt;The MCP Inspector, the protocol's own debugging client, has a command-line mode that connects, sends one request and prints the answer. Asked for &lt;code&gt;tools/list&lt;/code&gt;, the reference server returns fourteen tools, each with a description, an input schema and four annotations: &lt;code&gt;readOnlyHint&lt;/code&gt;, &lt;code&gt;destructiveHint&lt;/code&gt;, &lt;code&gt;idempotentHint&lt;/code&gt; and &lt;code&gt;openWorldHint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two of them deserve a second look.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;th&gt;What it actually does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get-env&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;readOnlyHint: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns every environment variable, including the &lt;code&gt;DEMO_API_KEY&lt;/code&gt; set for the test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gzip-file-as-resource&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openWorldHint: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetches whatever URL it is given, from the machine the server runs on&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;get-env&lt;/code&gt; really does change nothing, so its annotation is honest. Read-only describes side effects, not confidentiality. Annotations are also claims a server makes about itself, and the specification tells clients to treat them as untrusted unless the server itself is trusted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Engineering Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gzip-file-as-resource&lt;/code&gt; is not marked destructive, yet a model, or text an attacker planted somewhere the model reads, can give it any URL: a router's admin page, a service on localhost, or a cloud metadata endpoint such as &lt;code&gt;169.254.169.254&lt;/code&gt;. The response lands in the model's context. That is server-side request forgery, and &lt;code&gt;openWorldHint: true&lt;/code&gt; is the only clue in the annotations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Allow only what you decided
&lt;/h2&gt;

&lt;p&gt;In Claude Code, add the server and then deny the tools you do not want a model to have, in the project's &lt;code&gt;.claude/settings.local.json&lt;/code&gt;:&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;"permissions"&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;"deny"&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="s2"&gt;"mcp__everything__get-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp__everything__gzip-file-as-resource"&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;A denied MCP tool is removed from the model's context entirely, not merely refused when called. In Codex, list the only tools the server may expose with &lt;code&gt;enabled_tools&lt;/code&gt;. Of the two, the allow list is safer when a server can grow, because a tool added in a later version stays off until you choose to enable it.&lt;/p&gt;

&lt;p&gt;A stdio server runs as you, with your files, your network and your environment variables. Installing one is running a program, not adding a bookmark.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/read-an-mcp-server-first?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/mcp-for-developers.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#use-servers" rel="noopener noreferrer"&gt;Use a server before you build one&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>security</category>
      <category>agents</category>
    </item>
    <item>
      <title>Build the safety net before your coding agent's first edit</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Fri, 23 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/build-the-safety-net-before-your-coding-agents-first-edit-2076</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/build-the-safety-net-before-your-coding-agents-first-edit-2076</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4cbzmdop6r4pnxcm4fc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4cbzmdop6r4pnxcm4fc.png" alt="Four stacked safety layers around a coding agent. 1, permissions: which actions need your approval, using Claude Code permission modes or the Codex approval policy. 2, sandbox: what an approved command can reach, enforced by the operating system. 3, checkpoints: rewind the agent's own file edits with /rewind; shell commands are not tracked. 4, Git: restores anything inside the repository, but not databases, packages or sent messages." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sooner or later a coding agent will do something you did not ask for. It will edit a file you never mentioned, run a command that changes more than it should, or make a failing test pass by weakening the test. Better instructions make that rarer. They never make it impossible.&lt;/p&gt;

&lt;p&gt;What you can control is the damage: how much an unwanted action can touch, and how fast you can undo it. That is a setup task, not a prompting skill, and you do it once per project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four layers, each covering the last one's blind spot
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Permissions decide which actions need your yes.&lt;/strong&gt; Claude Code calls them permission modes and rules; Codex calls it the approval policy. In a codebase you do not know yet, choose a mode that asks before it edits, so you can see which files the agent reads and which commands it reaches for. The fully automatic modes are useful later, once you trust the project's setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The sandbox decides what an approved command can reach.&lt;/strong&gt; Files outside the project and the network are the usual boundaries, and the operating system enforces them. That matters because the model can be wrong about what a command does: inside Codex's &lt;code&gt;workspace-write&lt;/code&gt; sandbox, a write inside the project folder succeeds, while a write to your home folder and a request to the npm registry both fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Checkpoints rewind the agent's own edits.&lt;/strong&gt; Claude Code saves one with every prompt, and &lt;code&gt;/rewind&lt;/code&gt; restores the code, the conversation or both. It undoes a wrong direction in seconds, with one large exception below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Git restores anything inside the repository&lt;/strong&gt;, including what shell commands changed. It restores nothing outside it: not a database, not an installed package, not a message that was sent.&lt;/p&gt;

&lt;p&gt;No layer is enough alone. Git cannot recall a published package, and permissions cannot undo an edit you approved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git first: one branch and a clean tree per task
&lt;/h2&gt;

&lt;p&gt;Start every task from a clean working tree on its own branch. Then "what did the agent change?" always has an exact answer, and abandoning an attempt costs nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status                     &lt;span class="c"&gt;# must say "nothing to commit"&lt;/span&gt;
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; tb-101-overdue   &lt;span class="c"&gt;# one branch per task&lt;/span&gt;
&lt;span class="c"&gt;# ... the agent works ...&lt;/span&gt;
git diff &lt;span class="nt"&gt;--stat&lt;/span&gt;                &lt;span class="c"&gt;# which files changed, and how much&lt;/span&gt;
git diff                       &lt;span class="c"&gt;# every changed line&lt;/span&gt;
git stash &lt;span class="nt"&gt;-u&lt;/span&gt;                   &lt;span class="c"&gt;# set an attempt aside, untracked files included&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit whenever the tests pass, even halfway through a task. Small commits turn a bad turn into a few minutes of work instead of an afternoon, and they let you show the agent exactly which change broke something.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Mistake&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Trusting the working tree after a rewind. Checkpoints track only the edits Claude Code makes with its file tools. A file moved with &lt;code&gt;mv&lt;/code&gt;, deleted with &lt;code&gt;rm&lt;/code&gt;, regenerated by a script or changed by a database migration stays changed. After any rewind, run &lt;code&gt;git status&lt;/code&gt; and &lt;code&gt;git diff&lt;/code&gt; to see what is really there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The settings to leave alone
&lt;/h2&gt;

&lt;p&gt;Both tools have a mode that removes every boundary at once. They exist for containers and virtual machines that are already isolated, not for your laptop. When a task needs one extra capability, such as network access to install a package, grant that one thing for that session, or run the install yourself and let the agent continue.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/coding-agent-safety-net?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/codex-claude-code-and-mcp.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#safety-net" rel="noopener noreferrer"&gt;Build a safety net before the first edit&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>Your database reads pages, not rows</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/your-database-reads-pages-not-rows-en2</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/your-database-reads-pages-not-rows-en2</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51j95egyeqs4hjhmbdm8.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51j95egyeqs4hjhmbdm8.png" alt="One customer's 200 orders, found by the same index. A row is 120 bytes and an 8 KiB page holds 55 rows in PostgreSQL. Inserted over three years, the rows are scattered across 200 pages: 200 page reads. Loaded in customer order, they fill 4 pages: 4 page reads. 50 times apart. The index tells the engine where to look; locality decides how many pages it must read." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You ask for one 120-byte row. The storage engine reads an 8 KiB page, because that is the smallest unit the disk and the buffer pool exchange. If your row sits alone on that page, you paid 8 KiB for 120 bytes. If the neighbours you also wanted are on it too, you paid 8 KiB for all of them.&lt;/p&gt;

&lt;p&gt;That ratio is locality, and it is the most useful single lens for reasoning about storage performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How many rows share a page
&lt;/h2&gt;

&lt;p&gt;With nothing else taking space, an 8 KiB page would hold 68 rows of 120 bytes. A PostgreSQL heap page also spends 24 bytes on its page header and, for every row, 4 bytes on a line pointer and 24 on a tuple header (23 bytes, padded), so it holds 55.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;page_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;
&lt;span class="n"&gt;ideal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page_bytes&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;row_bytes&lt;/span&gt;                       &lt;span class="c1"&gt;# 68 rows
&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_bytes&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;row_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 55 rows
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Same index, fifty times apart
&lt;/h2&gt;

&lt;p&gt;Two tables hold the same customer's 200 orders, and the same index finds them in both. In the first, the orders were inserted over three years, so they are scattered across about 200 pages written at different times. The second was bulk-loaded in customer order last night, so the 200 rows sit side by side.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;How the rows are stored&lt;/th&gt;
&lt;th&gt;Page reads for 200 rows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scattered&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clustered, 68 rows a page&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clustered, PostgreSQL's 55 rows a page&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The index tells the engine where to look. It does not reduce the number of pages the engine must fetch; locality does. That is how "the query returns 200 rows and takes 400 ms" happens with a perfectly good index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most pages never touch the disk
&lt;/h2&gt;

&lt;p&gt;Pages are usually served from the buffer pool, the memory the engine keeps for hot pages, where a hit costs a memory access instead of an I/O. A hit ratio above 99% is normal on a well-sized database, which makes the ratio a poor alarm: a table scan that evicts the working set can keep it high while ruining every other query's locality. What matters is not how often you hit, but what was evicted to make room.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Think Like an Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A database with 64 GiB of RAM and a 60 GiB working set can be an order of magnitude faster than the same database with a 70 GiB working set. With uniform access there is no gradual decline, because the set either fits or it does not. Skewed access softens the cliff: the hot part of a 70 GiB set may still fit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a query is slow despite a good index, count pages, not rows.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/database-reads-pages?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/databases-at-scale.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#pages" rel="noopener noreferrer"&gt;The Database Does Not Read Rows&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>performance</category>
      <category>sql</category>
    </item>
    <item>
      <title>Why Kafka is a log, not a queue</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Tue, 20 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/why-kafka-is-a-log-not-a-queue-304c</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/why-kafka-is-a-log-not-a-queue-304c</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F788i44cnptwew8fddrx3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F788i44cnptwew8fddrx3.png" alt="Comparison. A queue deletes messages on delivery to competing workers: no second reader, no replay, and the broker tracks every message. A Kafka topic is an append-only log, offsets 0 to 9, kept by retention; consumer group A is at offset 9 and group B at offset 4. Reading doesn't delete, a new reader is a new group, and replay is an offset reset." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A traditional message queue deletes a message once it has been delivered and acknowledged. It sounds like tidy housekeeping. In practice it causes three problems you have probably met.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You cannot add a second independent reader.&lt;/strong&gt; Marketing wants every order event too, but the fulfilment workers already share each message between them. A second view needs a fan-out topology, publishing twice, or another copy of the data somewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You cannot replay.&lt;/strong&gt; A bug in the fulfilment consumer mishandled nine hours of orders. The messages are gone, so the fix is a one-off backfill script against the database, rebuilding events that used to exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The broker tracks every message's fate&lt;/strong&gt;: delivered, acknowledged, redelivered, dead-lettered. That bookkeeping is a large part of what makes queues hard to scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a log changes
&lt;/h2&gt;

&lt;p&gt;A Kafka topic is an append-only log kept according to a retention policy, not consumed away. Reading does not delete. A consumer group records only how far it has read in each partition, its offset. Adding a reader means adding a group with its own offsets. Replaying nine hours means moving a group's offsets back nine hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The price of storing one number
&lt;/h2&gt;

&lt;p&gt;Within a traditional consumer group, a partition's progress is a single integer. That is what makes fan-out and replay cheap, and it is also why the group cannot say "this one record failed, deliver just that one again" while moving past it. One stuck record blocks its partition, which is why Kafka designs end up with a dead-letter topic.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Queue&lt;/th&gt;
&lt;th&gt;Kafka consumer group&lt;/th&gt;
&lt;th&gt;Kafka share group&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Second independent reader&lt;/td&gt;
&lt;td&gt;needs fan-out or double publishing&lt;/td&gt;
&lt;td&gt;yes, a new group&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replay nine hours&lt;/td&gt;
&lt;td&gt;no, the messages are gone&lt;/td&gt;
&lt;td&gt;yes, reset the offsets&lt;/td&gt;
&lt;td&gt;yes, from the retained log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acknowledge one record&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no, progress is one number per partition&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ordering&lt;/td&gt;
&lt;td&gt;lost with competing consumers&lt;/td&gt;
&lt;td&gt;per partition&lt;/td&gt;
&lt;td&gt;weakened&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallelism ceiling&lt;/td&gt;
&lt;td&gt;number of consumers&lt;/td&gt;
&lt;td&gt;number of partitions&lt;/td&gt;
&lt;td&gt;beyond the partition count&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Share groups, available from Kafka 4.2, bring back per-record acknowledgement, and with it per-record bookkeeping and weaker ordering. They are a different trade, not a newer version of the same thing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Think Like an Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A team wants both fan-out and per-record acknowledgement on one topic. They can have it with two groups of different kinds on the same log: a consumer group for the reader that needs per-key order and replay, and a share group for the worker that needs to skip failures. What no single group can offer is both, because skipping a record and keeping that key's order are the same decision seen from two sides.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The useful question about a topic is which of those columns its readers need. A topic carrying changes to an order's state needs per-partition ordering. A topic of independent work items may not.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/kafka-log-not-queue?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/kafka-and-event-driven-systems.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#why-log" rel="noopener noreferrer"&gt;Why a Log, and Not a Queue&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>eventdriven</category>
      <category>systemdesign</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Your context window is a budget</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Sun, 18 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/your-context-window-is-a-budget-19pd</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/your-context-window-is-a-budget-19pd</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvlnhd2nme90tzcha3msf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvlnhd2nme90tzcha3msf.png" alt="A token budget for a hypothetical 8,192-token window: 1,024 reserved for the answer and 512 for message framing and estimation error leave an input allowance of 6,656. Instructions take 700, tool schemas 1,000, and the current task plus typed state 700, leaving 4,256 for evidence and history. Six 800-token evidence chunks need 4,800 and are over by 544; five need 4,000 and fit, but may drop the exception. Rank whole bundles: a rule plus its exceptions, all or nothing." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every token you put in front of a model is paid for three times: in money, in latency, and in the model's attention. A bigger context window raises the ceiling. It does not change the job, which on every turn is to send the smallest set of tokens that lets the model answer correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five lines in the budget
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Budget line&lt;/th&gt;
&lt;th&gt;Grows with&lt;/th&gt;
&lt;th&gt;Lever&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System prompt&lt;/td&gt;
&lt;td&gt;Policy and operating instructions&lt;/td&gt;
&lt;td&gt;Keep it precise, versioned, and stable where caching applies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool schemas&lt;/td&gt;
&lt;td&gt;The capabilities exposed in this state&lt;/td&gt;
&lt;td&gt;Expose tools per task, or let the agent discover them progressively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conversation state&lt;/td&gt;
&lt;td&gt;Raw turns, summaries, persisted facts&lt;/td&gt;
&lt;td&gt;Compact it, and retrieve what this decision needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieved context&lt;/td&gt;
&lt;td&gt;Number of chunks × chunk size&lt;/td&gt;
&lt;td&gt;Rerank so the count stays small and precise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-term memory&lt;/td&gt;
&lt;td&gt;How much is pulled in per turn&lt;/td&gt;
&lt;td&gt;Retrieve the few relevant memories, not the whole profile&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two of these lines are easy to underestimate. In runtimes that send every registered tool on every turn, irrelevant schemas use up input tokens and can make choosing the right tool harder. And replaying every raw turn of a conversation grows without limit unless the application compacts it, summarizes it, or retrieves only the state the current decision needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do the arithmetic before choosing context
&lt;/h2&gt;

&lt;p&gt;Take a hypothetical 8,192-token window. Reserve 1,024 tokens for the answer and 512 for message framing and estimation error, which leaves an input allowance of 6,656. Instructions take 700, tool schemas 1,000, the current task 200 and typed state 500: 2,400 spent before any evidence, and 4,256 left for evidence and history.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8,192 - 1,024 answer - 512 framing      = 6,656 input allowance
6,656 - (700 + 1,000 + 200 + 500)       = 4,256 for evidence and history

6 chunks x 800 = 4,800   over by 544
5 chunks x 800 = 4,000   fits, with 256 to spare
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use your provider's exact token accounting, including any reasoning or output limits. A rough counter is only an estimate, and the budget is only as good as its numbers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Mistake&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Taking the top five chunks because five fit. The sixth may be the exception to a rule stated in the first five, and a prompt that holds the rule without its exception produces a confident, wrong answer. Rank whole evidence bundles, a rule together with its exceptions, and include each bundle completely or not at all. If the bundle the question needs does not fit, report insufficient context rather than answering from part of it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The principle that makes retrieval work, a handful of highly relevant chunks beating a large dump, applies to the whole session. Every line of the budget competes for the same window.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/context-window-budget?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/agentic-ai-practitioners-companion.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#context-budget" rel="noopener noreferrer"&gt;The Context Window Budget&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>agents</category>
    </item>
    <item>
      <title>Pick the place before you pick the model</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Fri, 16 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/pick-the-place-before-you-pick-the-model-371o</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/pick-the-place-before-you-pick-the-model-371o</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F05a0a8c3s30llsik13m7.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F05a0a8c3s30llsik13m7.png" alt="Diagram mapping six kinds of job to where each belongs: a question or one-off code to a chat; recurring work with the same files and rules to a project or skill; a question that needs many sources to a research mode; a multi-step task with files, a browser or a schedule to a task hand-off; changes across a repository that must be run and tested to a coding agent such as Claude Code or Codex; a task inside your own program, run many times, to an API." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three decisions sit in front of every request you make to ChatGPT or Claude: where you ask, which model answers, and how much reasoning you ask it to spend. Developers argue about the second and ignore the first. Yet most disappointing answers come from asking in the wrong place, and most wasted money comes from the other two choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six jobs, six places
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The job&lt;/th&gt;
&lt;th&gt;Where it belongs&lt;/th&gt;
&lt;th&gt;Why there&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A question, an explanation or a one-off piece of code&lt;/td&gt;
&lt;td&gt;A chat&lt;/td&gt;
&lt;td&gt;You check the answer by reading it, so a conversation is enough.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recurring work with the same files and rules&lt;/td&gt;
&lt;td&gt;A project or a skill&lt;/td&gt;
&lt;td&gt;The context is set up once instead of pasted in every week.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A question that needs many sources&lt;/td&gt;
&lt;td&gt;A research mode&lt;/td&gt;
&lt;td&gt;It gathers and cites sources, and you check the sources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A multi-step task with files, a browser or a schedule&lt;/td&gt;
&lt;td&gt;Claude's task hand-off or ChatGPT's Work mode&lt;/td&gt;
&lt;td&gt;Built for a finished deliverable rather than a back-and-forth.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Changes across a repository that must be run and tested&lt;/td&gt;
&lt;td&gt;A coding agent such as Claude Code or Codex&lt;/td&gt;
&lt;td&gt;It can run the tests that prove the change works.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A task inside your own program, run many times with checked output&lt;/td&gt;
&lt;td&gt;An API&lt;/td&gt;
&lt;td&gt;Your code controls the input, the output format and the checks.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The boundaries are soft. A chat can write a whole module, and a coding agent can answer a question. The question that decides it is where the job is cheapest to check. A refactor that touches nine files is cheap to check where the tests can run, and expensive to check by eye in a chat window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then change one thing at a time
&lt;/h2&gt;

&lt;p&gt;Once the place is right, start from the mid-tier model at its default effort, and change something only for a reason you can name:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The answer missed something you supplied&lt;/strong&gt;, such as a constraint buried in a long file or two facts that interact. Raise the effort, or move up a tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The answer is wrong because it lacked information&lt;/strong&gt;, such as the file where the bug lives. No model fixes that. Supply the information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The task is routine&lt;/strong&gt;: renaming, reformatting, summarizing. Drop the effort or the tier. You wait less and use less of your allowance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A stronger model guesses more fluently
&lt;/h2&gt;

&lt;p&gt;Here is the trap the second rule protects you from. An assistant gives a wrong answer about how a search feature builds its query. The instinct is to switch to the biggest model. But if nobody attached the file that builds the query, the assistant was guessing, and a stronger model guesses more convincingly, not more correctly. Supply the evidence, ask again, and only then reach for more reasoning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Common Mistake&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assuming a ChatGPT or Claude subscription pays for API calls from your own program. The apps are covered by the subscription; the APIs are billed separately, by the token, through an API account. Both carry the same brand name, which is why teams mix them up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What changes for a team
&lt;/h2&gt;

&lt;p&gt;Before a team debates which model is better, it is worth asking where its AI work happens. Recurring prompts pasted into fresh chats every Monday, repository changes copied out of a chat window and never run, a script calling a chat product instead of an API: each is a placement problem that no model upgrade will solve. Fix the place, then tune the model, then tune the effort, in that order.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/pick-the-place-before-the-model?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/ai-tools-for-developers.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#plans-and-models" rel="noopener noreferrer"&gt;Choose the product, the model and the effort&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>A container is a process, not a small VM</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Wed, 14 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/a-container-is-a-process-not-a-small-vm-3o8o</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/a-container-is-a-process-not-a-small-vm-3o8o</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0smd7uk07f0gglihcljn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0smd7uk07f0gglihcljn.png" alt="Three layers around a container: namespaces restrict what it can see (its own processes, network, mounts and hostname), cgroups restrict what it can use (CPU time, memory, IO), and the kernel is not restricted, shared with the host and every container. Below, who receives SIGTERM on a deploy: with CMD ./start.sh the shell is PID 1 and many shells don't forward it, so the app gets SIGKILL after the grace period; with exec java -jar app.jar, or under tini or --init, the app is PID 1 and its shutdown hook runs. A note: older runtimes report the host's memory, so a heap sized for 64 GB inside a 512 MB container gets killed." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is no guest kernel inside a container, and nothing is virtualised. A container is an ordinary Linux process on the host; run &lt;code&gt;ps&lt;/code&gt; on the host and you will see it. What makes it a container is two kernel features wrapped around that process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Namespaces&lt;/strong&gt; restrict what it can see: its own process tree, network stack, mounts and hostname.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cgroups&lt;/strong&gt; restrict what it can use: CPU, memory and IO.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Picturing it as a small virtual machine is where most container surprises come from. Three of them turn up in support queues again and again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The kernel is shared
&lt;/h2&gt;

&lt;p&gt;Every container on a node runs on the host's kernel. A kernel vulnerability is therefore a host vulnerability, and a container escape is a real category of incident rather than a theoretical one. Containers are a convenient isolation boundary, but not one strong enough for running untrusted code from strangers. That needs a VM, Firecracker or gVisor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your process is PID 1
&lt;/h2&gt;

&lt;p&gt;Inside its PID namespace your application is process 1, and PID 1 plays by different rules: it gets no default signal handlers, and it must reap its zombie children. Whether a deploy shuts your service down cleanly depends on which process ends up in that slot.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Container command&lt;/th&gt;
&lt;th&gt;PID 1 is&lt;/th&gt;
&lt;th&gt;On SIGTERM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CMD ["java","-jar","app.jar"]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The JVM&lt;/td&gt;
&lt;td&gt;The shutdown handler runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CMD ./start.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The shell&lt;/td&gt;
&lt;td&gt;Many shells don't forward it, so SIGKILL arrives after the grace period&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run with tini or &lt;code&gt;--init&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;An init process&lt;/td&gt;
&lt;td&gt;Forwarded, and zombie children are reaped&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the mechanism behind a very common bug. The grace period is set correctly, the application implements shutdown correctly, and pods are still killed hard on every deploy, because a shell sits between the signal and the code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Think Like an Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The exec form &lt;code&gt;CMD ["./start.sh"]&lt;/code&gt; removes the wrapping shell, but the script still runs under its own interpreter, and that interpreter becomes PID 1. If the script ends with &lt;code&gt;exec java -jar app.jar&lt;/code&gt;, the JVM replaces it and receives the signal. Without that one &lt;code&gt;exec&lt;/code&gt;, nothing has changed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Memory limits are visible only if you look
&lt;/h2&gt;

&lt;p&gt;Older runtimes report the host's memory through the usual interfaces. A JVM or Node process then sizes its heap for a 64 GB machine while it lives in a 512 MB container, and the kernel's OOM killer ends it with a SIGKILL that no shutdown code can catch. Modern JVMs are container-aware by default. A lot of tuning advice, and a lot of running code, is not: anything that sizes a pool or a cache from "available system memory" will size it for the node.&lt;/p&gt;

&lt;p&gt;The tell is a container that dies at a limit far below what its configuration implies.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/container-is-a-process?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/containers-kubernetes-and-iac.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#what-container-is" rel="noopener noreferrer"&gt;A Container Is a Process With a Restricted View&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why a retry charges the customer twice</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Tue, 13 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/why-a-retry-charges-the-customer-twice-24ni</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/why-a-retry-charges-the-customer-twice-24ni</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07v4gjmkap9zjn39pqbo.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07v4gjmkap9zjn39pqbo.png" alt="Sequence diagram: the client sends a ₹4,998 charge, the payment service commits charge ch_0001, the reply is lost, the client times out after 2,000 ms and retries the same charge. Without an idempotency key the service creates a second charge and the customer pays ₹9,996; with a key it replays ch_0001 and the customer pays ₹4,998." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Order 88213 needs one payment of ₹4,998. The client calls the payment service with a 2,000 ms timeout and retries once on timeout, a policy many of us have written, and one that SDKs, service meshes and some HTTP clients apply without being asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five ordinary steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The client sends the charge.&lt;/li&gt;
&lt;li&gt;The payment service commits charge &lt;code&gt;ch_0001&lt;/code&gt;, then replies. That order is correct: replying before committing would confirm charges that never happened.&lt;/li&gt;
&lt;li&gt;The reply is lost on the way back.&lt;/li&gt;
&lt;li&gt;The client waits 2,000 ms and times out.&lt;/li&gt;
&lt;li&gt;The client retries, and the service, seeing what looks like a new instruction, commits &lt;code&gt;ch_0002&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The customer has paid ₹9,996 for a ₹4,998 order. Nothing exotic happened: no corrupted packet, no clock skew, no misbehaving node. A correct service, a correct client, a default retry policy and one lost response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The client cannot fix this
&lt;/h2&gt;

&lt;p&gt;After a timeout, the client does not know whether the first charge committed. It cannot find out by waiting longer or reasoning harder, because the information it needs never arrived. Removing the retry does not help either: then a request that really was lost leaves an order unpaid.&lt;/p&gt;

&lt;p&gt;So the repair has to happen at the other end. The service must be able to recognize the second request as a repeat of the first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an idempotency key changes
&lt;/h2&gt;

&lt;p&gt;The client creates one key for the payment, before the first attempt, and sends the same key with every retry. The service stores the key together with the charge it created, in the same transaction, with a uniqueness constraint on the key. When a request arrives with a key it has seen, the service returns the stored charge instead of creating a new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;charge(request):
  if a charge exists for request.idempotencyKey:
    return that charge          # a repeat: charge nothing
  in one transaction:
    create the charge
    record idempotencyKey -&amp;gt; charge
  return the charge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The uniqueness constraint matters when two copies of the same request arrive at once: only one of them can commit.&lt;/p&gt;

&lt;p&gt;Run the same five steps again and only step 5 differs: the service replays &lt;code&gt;ch_0001&lt;/code&gt;, and the customer pays ₹4,998.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Engineering Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key identifies the payment, not the HTTP request. A client that generates a fresh key for each attempt has added a header and fixed nothing, because every retry looks new.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where else this shows up
&lt;/h2&gt;

&lt;p&gt;Any operation with an effect outside the request is exposed to the same lost reply: sending an email, reserving stock, starting a job, calling another company's API. Before shipping a retry policy, it is worth asking of every endpoint it covers what happens when the work succeeds and only the answer disappears.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/why-a-retry-charges-twice?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/distributed-systems-for-production-engineers.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#duplicate-work" rel="noopener noreferrer"&gt;Why a Retry Charges the Customer Twice&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>systemdesign</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>What an AI agent actually is</title>
      <dc:creator>Ajitkumar Singh</dc:creator>
      <pubDate>Sun, 11 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ajitkumar_singh_7a94b3eaa/what-an-ai-agent-actually-is-39gb</link>
      <guid>https://dev.to/ajitkumar_singh_7a94b3eaa/what-an-ai-agent-actually-is-39gb</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mbjjfwdhlhblbfsc6o3.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3mbjjfwdhlhblbfsc6o3.png" alt="Comparison. A plain LLM call goes prompt, LLM, text, and the interaction ends. An agent runs Think, Act and Observe in a loop: the model proposes the next step, the runtime checks the tool request and calls the tool, and the real result goes back to the model, all inside a runtime that enforces max turns, a deadline, a cost limit and permissions. The model never touches the database; it emits a tool request that the orchestrator validates and runs." width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Agent" gets used for everything from a single function-calling request to a research bot that runs for days. Underneath, the idea is narrow. An agent is a language model placed inside a loop: it can take an action, see what happened, and decide what to do next, until it proposes an answer or the runtime stops it at a turn, time, cost or policy limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same model, different harness
&lt;/h2&gt;

&lt;p&gt;A plain model call is one round trip. You send a prompt, the model writes text from what it already knows plus whatever you pasted in, and the interaction is over. It cannot look anything up, check its own answer, or try again unless you send another request.&lt;/p&gt;

&lt;p&gt;Nothing about the model changes when it becomes an agent. What changes is the code around it. Instead of stopping after one response, the harness feeds the model's tool requests, and their results, back to it turn after turn.&lt;/p&gt;

&lt;p&gt;Take a hotel guest who writes "My AC isn't working." A plain call replies with sympathy and promises to contact maintenance; no ticket exists and nobody has been told. An agent identifies the guest and the room, checks the maintenance policy, creates a repair ticket, assigns available staff, starts the SLA clock and lets the guest know.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loop: think, act, observe
&lt;/h2&gt;

&lt;p&gt;An HR assistant has exactly one tool, &lt;code&gt;search_hr_docs(query)&lt;/code&gt;. Someone asks whether fathers can carry forward unused parental leave.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Think.&lt;/strong&gt; The answer needs the parental leave policy, so search for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act.&lt;/strong&gt; Call &lt;code&gt;search_hr_docs("parental leave")&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe.&lt;/strong&gt; "Fathers receive 30 days of parental leave." That answers how much, not whether it carries forward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act again.&lt;/strong&gt; Call &lt;code&gt;search_hr_docs("carry forward policy")&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe.&lt;/strong&gt; "Unused parental leave may carry forward up to 10 days into the next year."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop.&lt;/strong&gt; Both facts are in hand, so the model writes the answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have written retry logic, the shape is familiar, with one difference: the model proposes the next operation. The runtime still enforces a maximum number of turns, per-call deadlines, cancellation and a total cost allowance, however keen the model is to continue.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Engineering Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model never touches a database, an API or a file. It emits a structured tool request, and your orchestrator validates it, runs it and returns the result. The model reaches the outside world only through the capabilities your application chooses to expose.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Five parts, and where autonomy stops
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Decides the next step from everything observed so far&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools&lt;/td&gt;
&lt;td&gt;The only way to read or change anything outside the model's own text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory and context&lt;/td&gt;
&lt;td&gt;The current situation: this conversation and the tool results so far&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Policies and guardrails&lt;/td&gt;
&lt;td&gt;What the agent may and may not do, such as needing approval above a refund limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loop&lt;/td&gt;
&lt;td&gt;Runs think, act, observe, and checks whether to stop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The usual mistake is treating "agent" as all or nothing. In the hotel example the model is good at recognizing that "my AC is making a weird noise" is a maintenance request and picking the right workflow. The ticket lifecycle, the SLA calculation, permissions, approvals and audit events should stay deterministic code. Let the model decide which action fits; let your workflow engine decide how it runs.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://engineertoai.com/articles/what-an-ai-agent-is?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost" rel="noopener noreferrer"&gt;engineertoai.com&lt;/a&gt;. The full lesson is free, with no sign-up: &lt;a href="https://engineertoai.com/courses/ai-agents-agentic-rag-field-manual.html?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=crosspost#what-is-agent" rel="noopener noreferrer"&gt;What Is an AI Agent?&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
