<?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: Muhammad Azlaan Zubair</title>
    <description>The latest articles on DEV Community by Muhammad Azlaan Zubair (@mdazlaanzubair).</description>
    <link>https://dev.to/mdazlaanzubair</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%2F820665%2Fd4e80dec-bb09-4cf2-86bf-62322f57da44.png</url>
      <title>DEV Community: Muhammad Azlaan Zubair</title>
      <link>https://dev.to/mdazlaanzubair</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mdazlaanzubair"/>
    <language>en</language>
    <item>
      <title>AI Coding Tools and Productivity: What the Research Actually Found</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Thu, 12 Nov 2026 19:00:00 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/ai-coding-tools-and-productivity-what-the-research-actually-found-54ek</link>
      <guid>https://dev.to/mdazlaanzubair/ai-coding-tools-and-productivity-what-the-research-actually-found-54ek</guid>
      <description>&lt;p&gt;AI coding tools can make a developer feel faster while making a particular task take longer. They can increase the amount of code produced while also increasing review work, duplication, or security findings. Those statements are not necessarily contradictory. They describe different outcomes, measured at different levels.&lt;/p&gt;

&lt;p&gt;That distinction is the most useful way to read the research on AI coding tools and productivity. Controlled experiments measure task completion under defined conditions. Repository analyses observe patterns in code changes. Security evaluations test whether generated snippets choose safe implementations. Surveys capture adoption, trust, and perceived impact. None of those measurements is a substitute for all the others.&lt;/p&gt;

&lt;p&gt;The evidence supports neither a universal productivity boost nor a universal slowdown. It supports a narrower conclusion: AI changes the distribution of work. It can reduce effort in some tasks and contexts, while shifting cost into verification, integration, review, and maintenance. Teams need to measure those stages separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why developer productivity is difficult to measure
&lt;/h2&gt;

&lt;p&gt;“Productivity” sounds like one metric, but software development produces several outputs. A developer might finish a ticket sooner, write more code, resolve more tasks, reduce time spent searching, or improve a product outcome. Those are related, but they are not interchangeable.&lt;/p&gt;

&lt;p&gt;A randomized task experiment can compare time or completion between AI-assisted and unassisted conditions, but a short task may not represent work in a large codebase or include downstream review costs. Field experiments are more realistic but vary by task, tool, and team. Surveys capture adoption and sentiment, not causal task speed. Repository analyses reveal code-change patterns, but trends do not establish what caused them.&lt;/p&gt;

&lt;p&gt;A useful reading rule is to ask four questions before accepting a headline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Who or what was measured?&lt;/strong&gt; A developer, a task, a commit, a repository, a generated function, or a team?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What counted as success?&lt;/strong&gt; Less elapsed time, more completed work, accepted code, fewer defects, or a positive self-report?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What was the comparison?&lt;/strong&gt; No AI, a previous year, another team, a different model, or a vendor-defined baseline?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What remains outside the measurement?&lt;/strong&gt; Review, debugging, security, maintainability, onboarding, or the value of the shipped product?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without those details, “AI productivity” is too broad to be a useful conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controlled studies: faster in some settings, slower in others
&lt;/h2&gt;

&lt;p&gt;Controlled studies provide the clearest task-level comparisons, but their results depend heavily on the task and participants.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Copilot: a narrow task completed faster
&lt;/h3&gt;

&lt;p&gt;In a 2023 controlled experiment, 95 professional developers were randomly split between implementing a JavaScript HTTP server with or without GitHub Copilot. The Copilot group completed the task 55.8% faster on average. This is evidence for acceleration on a bounded task—not a universal speedup. The study did not measure long-term maintenance or team delivery, and tested an earlier version of the tool. &lt;a href="https://arxiv.org/abs/2302.06590" rel="noopener noreferrer"&gt;Read the study&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  METR: experienced maintainers took longer
&lt;/h3&gt;

&lt;p&gt;METR’s randomized controlled trial, published July 10, 2025, tested a different setting. Sixteen experienced open-source developers worked on 246 real issues in mature repositories they had contributed to for multiple years. The repositories averaged more than 22,000 stars and one million lines of code. Developers had moderate AI experience and an average of about five years of experience with the repositories.&lt;/p&gt;

&lt;p&gt;Each issue was randomly assigned to an AI-allowed or AI-disallowed condition. Participants could choose their tools; in the AI condition they primarily used Cursor Pro with Claude 3.5 or 3.7 Sonnet. Tasks averaged about two hours. Participants recorded their screens and self-reported implementation time. METR reported that allowing AI increased task completion time by 19%. Before the tasks, developers expected a 24% time reduction; afterward, they still estimated that AI had made them 20% faster.&lt;/p&gt;

&lt;p&gt;The result is striking because it contrasts perceived speed with measured time in a realistic, repository-specific setting. But METR explicitly cautioned against generalizing it to most developers or software work. The sample was small and highly experienced, and the tested tools represented the early-2025 frontier. METR also listed possible improvements in prompting, scaffolding, and repository-specific context as reasons the result might not transfer to other setups. &lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;Read METR’s study and its limitations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A February 2026 update described a later experiment with 57 developers, 143 repositories, and 800+ tasks. METR said selection effects made its estimates unreliable: some developers declined to work without AI, and 30%–50% said they withheld tasks they did not want to attempt without it. Raw estimates suggested possible speedups, but confidence intervals included no effect. The update does not erase the 2025 result; it reinforces that it was time- and context-bounded. &lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;Read the update&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three workplace field experiments: more tasks completed
&lt;/h3&gt;

&lt;p&gt;A study by Kevin Cui and co-authors combined three randomized field experiments at Microsoft, Accenture, and an anonymous Fortune 100 company. Across 4,867 developers given access to an AI code-completion assistant or not, the combined analysis found a 26.08% increase in completed tasks (standard error: 10.3%). Less experienced developers had higher adoption and larger gains.&lt;/p&gt;

&lt;p&gt;The individual experiments were noisy and varied. Completed task count is not the same as time per task or long-term code quality. The working paper was revised in August 2025 and published in &lt;em&gt;Management Science&lt;/em&gt; on February 27, 2026. It counters a blanket slowdown narrative, but covers code-completion assistants in three enterprise settings—not every agentic workflow. &lt;a href="https://doi.org/10.1287/mnsc.2025.00535" rel="noopener noreferrer"&gt;Read the study&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These studies disagree only if we treat task time, task count, and work context as the same outcome. A bounded JavaScript task, a mature open-source issue, and ordinary enterprise work create different opportunities for assistance and different costs of review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Large codebase analyses: quality signals, not a causal verdict
&lt;/h2&gt;

&lt;p&gt;GitClear’s February 2025 report, &lt;em&gt;AI Copilot Code Quality: Evaluating 2024’s Increased Defect Rate via Code Quality Metrics&lt;/em&gt;, analyzed 211 million meaningful changed lines from January 2020 through December 2024. Its data combined roughly two-thirds anonymized data from private corporations that opted in and one-third open-source projects, including projects associated with Google, Meta, and Microsoft.&lt;/p&gt;

&lt;p&gt;GitClear classified code changes into operations such as added, moved, updated, copy/pasted, and churned lines. It reported that moved lines—used as a proxy for refactoring—fell from 24.8% of changed lines in 2021 to 9.5% in 2024. Copy/pasted lines rose from 8.4% to 12.3% over the same period. In 2024, copy/pasted lines exceeded moved lines for the first time in the report’s series. GitClear also found that commits containing a duplicated block of at least five contiguous lines rose from 0.45% in 2022 to 6.66% in 2024 in the commits it scanned.&lt;/p&gt;

&lt;p&gt;These are maintainability signals, not direct measures of maintenance difficulty. Repeated code can create more places to update, but the time trend does not prove AI caused it or establish a randomized AI-versus-no-AI comparison. GitClear’s classification excludes generated files and other changes, includes comments, and does not separate test from production code. Its historical duplicate-block scan examined the largest 1,000 commits per repository for earlier years, which it says may bias those years toward finding more duplication. Treat the results as a reason to inspect local trends—not proof that AI-generated code is inherently duplicated. &lt;a href="https://gitclear-public.s3.us-west-2.amazonaws.com/GitClear-AI-Copilot-Code-Quality-2025.pdf" rel="noopener noreferrer"&gt;Read the report&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security research: code that compiles can still be unsafe
&lt;/h2&gt;

&lt;p&gt;Security studies test a narrower question than productivity studies: when a model is asked to generate code, does it choose a secure implementation?&lt;/p&gt;

&lt;p&gt;Veracode’s 2025 GenAI Code Security Report evaluated more than 100 language models using 80 code-completion tasks across Java, JavaScript, C#, and Python. The tasks covered four vulnerability classes: SQL injection, cross-site scripting, log injection, and use of broken or risky cryptographic algorithms. Each task supplied a short function with a missing implementation and a comment describing the desired behavior. Veracode ran static analysis against the generated code.&lt;/p&gt;

&lt;p&gt;Across the tested models and tasks, Veracode reported an average security pass rate of approximately 55%—meaning 45% of generated completions contained one of the known security flaws being tested. Results varied sharply by vulnerability type: models performed much better on SQL injection and cryptographic choices than on cross-site scripting and log injection. The report found little meaningful improvement in security performance across model sizes or release dates in its tested set.&lt;/p&gt;

&lt;p&gt;The limitation is central to the result. These were intentionally constrained function-completion tasks with minimal context and no security-specific prompting. Veracode did not check functional correctness; it checked compilation and the selected security properties using its own static analysis engine. The report therefore does not mean 45% of production AI code is vulnerable. It means the tested models often chose insecure implementations under these task conditions. The vendor’s own report discusses the trade-off and the narrowness of the test. &lt;a href="https://www.veracode.com/wp-content/uploads/2025_GenAI_Code_Security_Report_Final.pdf" rel="noopener noreferrer"&gt;Read the report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Apiiro’s September 2025 report looked at a different level: repository and developer activity inside Fortune 50 enterprises. Using its proprietary Deep Code Analysis engine, Apiiro analyzed tens of thousands of repositories and several thousand developers using a variety of coding assistants. It reported that AI-assisted developers produced three to four times more commits but fewer, larger pull requests; the company also reported ten times as many security findings, with more than 10,000 new findings per month by June 2025 compared with December 2024.&lt;/p&gt;

&lt;p&gt;Apiiro reported a mixed risk profile: syntax errors fell 76% and logic bugs fell by more than 60%, while privilege-escalation paths rose 322% and architectural design flaws rose 153%. It also reported that AI-assisted developers exposed certain Azure credentials nearly twice as often as non-AI peers.&lt;/p&gt;

&lt;p&gt;Those are Apiiro’s findings from its own enterprise telemetry, not an independently replicated causal experiment. The report does not provide enough public detail to independently reconstruct the full sampling, attribution, or normalization behind every comparison. Its “security findings” include a broad set of risks and should not be read as a count of confirmed exploitable vulnerabilities. The company also sells application-security products, so its commercial position belongs in the reader’s assessment. The evidence is a warning about the possible security workload created by high-volume changes, not a universal vulnerability multiplier. &lt;a href="https://apiiro.com/blog/4x-velocity-10x-vulnerabilities-ai-coding-assistants-are-shipping-more-risks" rel="noopener noreferrer"&gt;Read Apiiro’s report&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Surveys: adoption and trust are not productivity measurements
&lt;/h2&gt;

&lt;p&gt;The 2025 Stack Overflow Developer Survey received 49,009 responses from 177 countries. It was fielded from May 29 to June 23, 2025, with respondents recruited primarily through Stack Overflow-owned channels. The survey reported that 84% of respondents used or planned to use AI tools in their development process, while 51% of professional developers said they used AI tools daily.&lt;/p&gt;

&lt;p&gt;The same survey showed a trust gap: 46% distrusted AI output accuracy, compared with 33% who trusted it; 66% reported frustration with answers that were almost right, and 45% said debugging AI-generated code could take more time. These are self-reported sentiments, not causal productivity measures. Recruitment through Stack Overflow-owned channels also means the sample is not a probability sample of every developer worldwide. &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Read the survey and methodology&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DORA’s 2025 &lt;em&gt;State of AI-assisted Software Development&lt;/em&gt; report used survey responses from nearly 5,000 technology professionals and more than 100 hours of qualitative data. The survey ran from June 13 to July 21, 2025. DORA reported that 90% of respondents used AI at work and more than 80% believed it increased their productivity. Its analysis associated greater AI adoption with higher software delivery throughput and product performance, but also with greater software delivery instability. DORA’s central interpretation was that AI amplifies the strengths and weaknesses of the surrounding organizational system.&lt;/p&gt;

&lt;p&gt;This is organizational evidence, not a randomized trial of individual task speed. The reported relationships are associations, not proof that AI alone caused a team to improve or deteriorate. DORA moves the question beyond typing speed to whether increased output becomes a better product. &lt;a href="https://dora.dev/research/2025/dora-report/" rel="noopener noreferrer"&gt;Read DORA’s 2025 research overview&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the evidence agrees—and where it does not
&lt;/h2&gt;

&lt;p&gt;Across these sources, several patterns are consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Perceived productivity is not measured productivity.&lt;/strong&gt; METR’s 2025 participants believed AI helped even when their measured task time increased. Surveys capture perception; experiments can compare observed task outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task and context matter.&lt;/strong&gt; A narrow implementation task, a mature repository issue, and enterprise delivery work do not test the same capability. Results should not be averaged into one universal speedup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More code is not the same as more value.&lt;/strong&gt; Commit volume, lines changed, and completed tasks are output measures. They do not automatically account for review cost, defects, maintainability, or product outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification remains part of the work.&lt;/strong&gt; Veracode and Apiiro identify security risks under different methods, while Stack Overflow respondents report trust and debugging concerns. DORA connects AI adoption to delivery instability as well as throughput.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The disagreements are also real. GitHub’s bounded task, Microsoft’s three field experiments, and DORA’s 2025 organizational analysis report positive productivity or throughput signals. METR’s 2025 RCT reports a slowdown for experienced maintainers working on their own repositories. GitClear’s code-change trends and Apiiro’s security telemetry identify possible downstream costs. These findings should not be collapsed into a vote. They differ in period, tools, participants, tasks, outcomes, and measurement units.&lt;/p&gt;

&lt;h2&gt;
  
  
  What engineering teams should measure
&lt;/h2&gt;

&lt;p&gt;For an engineering manager, the practical response is not to choose the most optimistic or pessimistic paper. It is to run a local evaluation that separates the stages where AI may save or add work.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Choose representative tasks.&lt;/strong&gt; Include routine implementation, unfamiliar code, bug fixes, refactoring, tests, documentation, and cross-service changes. Do not benchmark only the tasks where the tool is strongest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record total cycle time.&lt;/strong&gt; Measure from task start to accepted merge, including prompting, waiting, debugging, review, rework, and test failures. Keep active developer time separate from elapsed time when agents run asynchronously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure accepted outcomes.&lt;/strong&gt; Track completed and accepted tasks, review rounds, change size, reverts, escaped defects, and rework. Avoid treating lines of code or commits as productivity by themselves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect maintainability.&lt;/strong&gt; Track duplication, churn, refactoring, dependency changes, and the age of code being modified. Compare these measures against your own baseline rather than assuming GitClear’s dataset describes your repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add security checks.&lt;/strong&gt; Review authentication and authorization boundaries, data handling, secrets, dependency provenance, and security-sensitive code paths. Static analysis and tests are useful controls, but neither replaces architectural review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segment the results.&lt;/strong&gt; Compare by task type, developer experience, repository familiarity, tool/model, and workflow. A team-wide average can hide where assistance helps and where it creates rework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-evaluate after tool changes.&lt;/strong&gt; Model capabilities and agent workflows change quickly. A result from early 2025 is not a permanent property of AI-assisted development.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most useful baseline is the team’s existing performance on comparable work. Run a small, time-bounded pilot, define success before starting, and keep the evaluation long enough to observe review and rework—not just initial code generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I think: verification is the missing denominator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;My interpretation:&lt;/strong&gt; the central mistake in many AI productivity claims is measuring the generation step as though it were the whole engineering task. Code can appear quickly, but it still has to be understood, tested, reviewed, secured, integrated, and maintained. If the measurement ends when code is produced, it misses the work that determines whether the output is useful.&lt;/p&gt;

&lt;p&gt;That is why verification deserves to be measured as a first-class part of the workflow. It is also the connection to two related Letinix essays: &lt;em&gt;Code Generation Is Fast. Verification Is Not.&lt;/em&gt; and &lt;em&gt;The Competence Debt of Agentic Coding&lt;/em&gt;. The first explores the verification bottleneck; the second examines the risk of delegating work that the developer can no longer confidently explain or assess. Their URLs were not supplied with this assignment, so they are noted for internal linking rather than linked to guessed destinations.&lt;/p&gt;

&lt;p&gt;This is an editorial judgment, not a result directly established by any one study. The research supports the need to distinguish output, time, quality, security, and trust. It does not yet provide one agreed metric that captures the full value of AI-assisted engineering across organizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do next
&lt;/h2&gt;

&lt;p&gt;If you want to use AI more deliberately, start with the &lt;a href="https://letinix.com/resources/ai-prompt-pack-for-developers" rel="noopener noreferrer"&gt;AI Prompt Pack for Developers&lt;/a&gt;. Treat prompts as a way to improve task framing and context—not as a substitute for code review, tests, security analysis, or engineering judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2302.06590" rel="noopener noreferrer"&gt;The Impact of AI on Developer Productivity: Evidence from GitHub Copilot — Peng et al.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/" rel="noopener noreferrer"&gt;Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity — Becker et al., METR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metr.org/blog/2026-02-24-uplift-update/" rel="noopener noreferrer"&gt;We are Changing our Developer Productivity Experiment Design — METR, February 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doi.org/10.1287/mnsc.2025.00535" rel="noopener noreferrer"&gt;The Effects of Generative AI on High-Skilled Work: Evidence from Three Field Experiments with Software Developers — Cui et al.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitclear-public.s3.us-west-2.amazonaws.com/GitClear-AI-Copilot-Code-Quality-2025.pdf" rel="noopener noreferrer"&gt;AI Copilot Code Quality: Evaluating 2024’s Increased Defect Rate via Code Quality Metrics — GitClear, February 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.veracode.com/wp-content/uploads/2025_GenAI_Code_Security_Report_Final.pdf" rel="noopener noreferrer"&gt;2025 GenAI Code Security Report — Veracode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apiiro.com/blog/4x-velocity-10x-vulnerabilities-ai-coding-assistants-are-shipping-more-risks" rel="noopener noreferrer"&gt;4x Velocity, 10x Vulnerabilities: AI Coding Assistants Are Shipping More Risks — Apiiro, September 2025&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://survey.stackoverflow.co/2025/" rel="noopener noreferrer"&gt;2025 Stack Overflow Developer Survey — Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dora.dev/research/2025/dora-report/" rel="noopener noreferrer"&gt;State of AI-assisted Software Development — DORA, 2025&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/analyze/ai-coding-productivity-research" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Back-of-the-Envelope Estimation for System Design, With Worked Examples</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 10 Nov 2026 19:00:00 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/back-of-the-envelope-estimation-for-system-design-with-worked-examples-2gni</link>
      <guid>https://dev.to/mdazlaanzubair/back-of-the-envelope-estimation-for-system-design-with-worked-examples-2gni</guid>
      <description>&lt;p&gt;System design estimation is a way to turn an ambiguous product description into approximate traffic, storage, bandwidth, and capacity requirements. The goal is not to predict an exact production number. It is to expose the order of magnitude, make assumptions visible, and identify which part of the design deserves attention first.&lt;/p&gt;

&lt;p&gt;A useful estimate follows a repeatable sequence: define the workload, calculate average and peak requests per second, split reads from writes, estimate data growth, calculate network throughput, and translate the results into design choices. The arithmetic should be simple enough to explain aloud and detailed enough for another engineer to challenge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Treat every number in the worked examples as an explicit hypothetical input, not a benchmark or a universal industry default. Replace assumptions with measured product analytics, load tests, payload samples, and retention requirements when sizing a real system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The estimation method: assumptions before formulas
&lt;/h2&gt;

&lt;p&gt;Start by describing what the system does. “A social feed” is not a workload; “two million daily active users each request twenty feed pages and publish half a post per day on average” is a workload you can calculate.&lt;/p&gt;

&lt;p&gt;Write down the assumptions before doing arithmetic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Users and activity:&lt;/strong&gt; daily active users (DAU), actions per user, and whether actions happen evenly or in bursts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operation mix:&lt;/strong&gt; reads, writes, uploads, downloads, background jobs, and internal fan-out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload sizes:&lt;/strong&gt; average request, response, record, and file sizes. Keep ingress and egress separate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retention:&lt;/strong&gt; how long records, events, files, and derived data remain available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic shape:&lt;/strong&gt; observed peak-to-average ratio, seasonal events, regional time zones, and retry behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capacity target:&lt;/strong&gt; the utilization or headroom the system should retain during normal and degraded operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask which values are known, which are estimates, and which are deliberately conservative. If a prompt does not provide a value, choose a round assumption, say why it is plausible for the scenario, and show how the result changes if it is wrong. In an interview, this is part of the answer—not a detour before the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The conversions worth keeping close
&lt;/h2&gt;

&lt;p&gt;A day contains 86,400 seconds. For quick mental arithmetic, 100,000 seconds is a convenient approximation, but use 86,400 when showing a worked calculation. The approximation makes the result about 13.6% lower than the exact division, so it is useful for a first pass, not a substitute for checking a decision near a capacity boundary.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time interval&lt;/th&gt;
&lt;th&gt;Seconds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 day&lt;/td&gt;
&lt;td&gt;86,400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30-day month&lt;/td&gt;
&lt;td&gt;2,592,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;365-day year&lt;/td&gt;
&lt;td&gt;31,536,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For traffic, remember the order of magnitude: one million requests per day is 1,000,000 ÷ 86,400 = 11.57 requests per second, or roughly 12 average requests per second. Ten million per day is about 116/s; one hundred million per day is about 1,157/s.&lt;/p&gt;

&lt;p&gt;Be precise about data units. Decimal units use powers of 10: 1 MB = 1,000,000 bytes and 1 GB = 1,000,000,000 bytes. Binary units use powers of 2: 1 KiB = 1,024 bytes, 1 MiB = 1,048,576 bytes, and 1 GiB = 1,073,741,824 bytes. NIST documents the distinction between SI and IEC binary prefixes. &lt;a href="https://pml.nist.gov/cuu/Units/binary.html" rel="noopener noreferrer"&gt;NIST: Definitions of the SI units — binary prefixes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use one convention throughout a calculation. In the examples below, storage totals use decimal GB and TB; file sizes use MiB where binary units are more natural. State the convention rather than switching between MB and MiB as if they were identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core formulas for system design estimation
&lt;/h2&gt;

&lt;p&gt;These formulas provide a starting model. They do not capture every system cost, but they expose the main quantities that influence an initial architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Average and peak request rate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requests_per_day = DAU × requests_per_user_per_day
average_RPS      = requests_per_day ÷ 86,400
peak_RPS         = average_RPS × peak_to_average_factor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RPS means requests per second. QPS means queries per second; teams sometimes use the terms interchangeably, but define whether a “request” is an external API call, a database query, or an internal operation. One external request can fan out into several internal calls.&lt;/p&gt;

&lt;p&gt;Do not assume one peak factor fits every product. Calculate it from observed time-bucketed traffic when possible: peak interval rate divided by the average rate for the same interval definition. If no telemetry exists, state a scenario assumption and test alternatives. A factor of 3 in an example means “we are modeling a peak three times the average,” not “all systems peak at 3×.”&lt;/p&gt;

&lt;p&gt;Calculate read and write rates separately. A read-heavy product may need to serve a large volume of repeated data, while a write-heavy product may need sustained ingestion, ordering, durability, or downstream processing. A combined RPS figure can hide the real constraint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage growth
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new_data_per_day = writes_per_day × average_record_size
logical_storage  = new_data_per_day × retention_days
physical_storage = logical_storage × copy_factor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add indexes, metadata, compaction space, snapshots, backups, and derived data separately. A copy factor is a simplified planning input, not a universal statement about how a managed database or object store implements durability. Compression also changes the stored size; estimate it from representative data rather than assuming a fixed saving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network bandwidth
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bytes_per_second = requests_per_second × average_payload_bytes
bits_per_second  = bytes_per_second × 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calculate ingress and egress independently. Use the relevant request or response size for each path. Add protocol overhead, encryption, retries, fan-out, and retransmission where they materially affect the estimate. For large files, a small request count can still produce substantial bandwidth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server count
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;required_instances = ceil(peak_RPS ÷ sustainable_RPS_per_instance)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the capacity target is below full utilization, use &lt;code&gt;ceil(peak_RPS ÷ (sustainable_RPS_per_instance × target_utilization))&lt;/code&gt;. The per-instance rate must come from a representative load test or a defensible capacity measurement for the actual workload, software, instance type, and latency target. Do not copy a generic “requests per server” number into a design and present it as fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example 1: a read-heavy feed
&lt;/h2&gt;

&lt;p&gt;Assume a feed service has 2 million daily active users. Each user loads twenty feed pages per day and creates half a post per day on average. Model peak traffic at four times the daily average. Assume each post record occupies 1,000 bytes and each feed response transfers 12,000 bytes. These are illustrative inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Calculate reads.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reads/day = 2,000,000 users × 20 reads = 40,000,000
average read RPS = 40,000,000 ÷ 86,400 = 462.96 ≈ 463
peak read RPS = 463 × 4 ≈ 1,852
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Calculate writes.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;posts/day = 2,000,000 × 0.5 = 1,000,000
average write RPS = 1,000,000 ÷ 86,400 = 11.57 ≈ 11.6
peak write RPS = 11.57 × 4 = 46.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workload is roughly 40 reads for every write. That ratio does not prove a cache is required, but it tells you the read path deserves more attention than the write path in the first design pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Estimate response bandwidth.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;peak egress = 1,852 responses/s × 12,000 bytes
             = 22,224,000 bytes/s
             ≈ 22.2 MB/s ≈ 178 Mbps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is application response payload only. It excludes transport overhead and any media served separately. If feed responses include images, model image delivery as a separate path rather than hiding it inside an average API response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Estimate post storage.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new logical data/day = 1,000,000 posts × 1,000 bytes = 1 GB
one year              = 1 GB/day × 365 = 365 GB
three-copy scenario   = 365 GB × 3 = 1.095 TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 1.095 TB figure excludes indexes, metadata, backups, and media. It is not a complete database capacity plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design implications:&lt;/strong&gt; investigate caching or precomputing frequently requested feed data, and consider read replicas only if measured database read pressure justifies them. Keep writes on a simpler path initially unless ordering, fan-out, or consistency requirements change the picture. Separate media delivery from feed API responses, and validate the assumed read distribution: a highly personalized feed may not benefit from the same cache strategy as a feed of mostly shared content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example 2: a write-heavy event log
&lt;/h2&gt;

&lt;p&gt;Assume 500,000 daily active devices each emit 200 events per day. Each stored event, including its basic metadata, averages 600 bytes. Model peak ingestion at five times the average and retain events for 30 days. Use a three-copy scenario for a first storage estimate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Calculate event volume and ingestion rate.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events/day = 500,000 × 200 = 100,000,000
average write RPS = 100,000,000 ÷ 86,400 = 1,157.4
peak write RPS = 1,157.4 × 5 = 5,787
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Calculate storage.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;logical data/day = 100,000,000 × 600 bytes = 60,000,000,000 bytes
                 = 60 GB/day
30-day logical storage = 60 GB × 30 = 1.8 TB
three-copy scenario = 1.8 TB × 3 = 5.4 TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 5.4 TB estimate excludes indexes, compression effects, retention gaps, backups, and temporary compaction space. If event payloads vary substantially, calculate by event class or use a measured size distribution instead of relying on one average.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Check ingress bandwidth.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;peak ingress = 5,787 events/s × 600 bytes
              = 3,472,200 bytes/s
              ≈ 3.47 MB/s ≈ 27.8 Mbps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request rate is more revealing than the raw bandwidth in this example. The system must accept and durably process nearly 5,800 small events per second at the modeled peak, even though the byte rate is modest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design implications:&lt;/strong&gt; consider an append-oriented ingestion path, batching, and a durable queue or log when producers and consumers need decoupling. Partitioning can distribute sustained write volume, but the partition key must avoid concentrating one hot tenant or event type on a single partition. Define ordering requirements before choosing a partition strategy: global ordering is much more restrictive than per-device or per-aggregate ordering. Use retention and compaction policies that match the actual query and audit requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example 3: a file upload service
&lt;/h2&gt;

&lt;p&gt;Assume 100,000 daily active users upload two files each per day. The average file is 8 MiB. Model upload peaks at eight times the average. Assume each uploaded file is downloaded three times on average, downloads peak at four times their average, and files are retained for 30 days. For a simplified capacity scenario, count three stored copies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Calculate upload traffic.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uploads/day = 100,000 × 2 = 200,000
average upload RPS = 200,000 ÷ 86,400 = 2.31
peak upload RPS = 2.31 × 8 = 18.52
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request rate looks small. The payload size changes the capacity picture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Calculate upload bandwidth.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;peak ingress = 18.52 uploads/s × 8 MiB
             ≈ 155.3 MB/s ≈ 1.24 Gbps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The conversion uses 8 MiB = 8,388,608 bytes and decimal MB for the final rate. This is a payload estimate, not a provisioned network target; protocol overhead and burst shape still matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Calculate storage.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data/day = 200,000 × 8,388,608 bytes
         = 1.678 TB/day (decimal)
30-day logical storage = 1.678 TB × 30 ≈ 50.33 TB
three-copy scenario = 50.33 TB × 3 ≈ 150.99 TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Estimate download egress.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;downloads/day = 200,000 uploads × 3 = 600,000
average download RPS = 600,000 ÷ 86,400 = 6.94
peak download RPS = 6.94 × 4 = 27.78
peak egress = 27.78 × 8 MiB ≈ 233 MB/s ≈ 1.86 Gbps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Design implications:&lt;/strong&gt; this is a data-transfer and storage problem, not simply an API request-count problem. Consider direct-to-object-storage uploads using short-lived, scoped upload authorization so application servers do not proxy every file byte. Use asynchronous processing for malware scanning, metadata extraction, and thumbnail generation when those tasks do not need to block the upload response. A CDN may reduce origin egress for repeatedly downloaded files, subject to access control and cache policy. Confirm whether “three copies” is actually how the chosen storage service bills or exposes durability; do not multiply managed storage by three if its documented storage model already accounts for redundancy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare the three estimates
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Peak primary operation&lt;/th&gt;
&lt;th&gt;Data growth&lt;/th&gt;
&lt;th&gt;Main pressure to investigate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read-heavy feed&lt;/td&gt;
&lt;td&gt;~1,852 reads/s; ~46 writes/s&lt;/td&gt;
&lt;td&gt;1 GB/day logical posts&lt;/td&gt;
&lt;td&gt;Read path, cacheability, feed fan-out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write-heavy event log&lt;/td&gt;
&lt;td&gt;~5,787 writes/s&lt;/td&gt;
&lt;td&gt;60 GB/day logical events&lt;/td&gt;
&lt;td&gt;Sustained ingestion, partitioning, retention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload service&lt;/td&gt;
&lt;td&gt;~18.5 uploads/s; ~27.8 downloads/s&lt;/td&gt;
&lt;td&gt;~1.68 TB/day logical files&lt;/td&gt;
&lt;td&gt;Ingress/egress bandwidth and object storage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The examples are not directly comparable capacity benchmarks: their workloads, payloads, and assumptions differ. Their purpose is to show how the same method reveals different constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sanity checks before you trust the result
&lt;/h2&gt;

&lt;p&gt;Run these checks before turning estimates into an architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recalculate from the other direction.&lt;/strong&gt; Multiply average RPS by 86,400 and confirm that it returns the daily request count within rounding error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check units at every step.&lt;/strong&gt; Requests/s × bytes/request gives bytes/s. Multiply by eight only when converting bytes to bits. Do not label MB/s as Mbps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate external and internal work.&lt;/strong&gt; If one request causes five database queries or three downstream calls, estimate those operations separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check peak and average consistency.&lt;/strong&gt; Apply a peak factor to the same time unit and traffic category. Do not multiply a peak rate by a daily count again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the assumptions.&lt;/strong&gt; Recalculate with half and twice the assumed activity, payload size, or retention. If the design changes sharply, the assumption needs measurement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep logical and physical storage distinct.&lt;/strong&gt; State whether the estimate includes copies, indexes, backups, compression, and derived data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Look for missing workload dimensions.&lt;/strong&gt; Concurrent connections, background jobs, retries, batch windows, and hot-key skew can matter even when average RPS looks modest.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Turn estimates into design decisions
&lt;/h2&gt;

&lt;p&gt;An estimate is useful only when it changes a question or decision. Use the numbers to identify what to investigate—not to select a database or cache by formula alone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; consider it when reads repeat, data has an acceptable freshness window, and measured origin work is expensive. A high read/write ratio is a clue, not proof that every response is cacheable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replication:&lt;/strong&gt; separate read scaling, availability, and durability requirements. Replicas add operational and consistency considerations; they are not a universal response to high RPS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partitioning:&lt;/strong&gt; investigate it when write volume, storage growth, or data ownership exceeds a single partition's tested limits. Choose a key based on access patterns and skew, not only on even-looking IDs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queues and logs:&lt;/strong&gt; use them when ingestion and processing need independent scaling, buffering, replay, or failure isolation. They add delivery semantics and operational complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDNs and object storage:&lt;/strong&gt; consider them when large or repeated file transfers dominate bandwidth or application-server work. Access control and cache invalidation remain part of the design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capacity and headroom:&lt;/strong&gt; use representative load tests to estimate sustainable per-instance throughput at the latency and error-rate targets that matter. Then calculate instance count with the formula above and add failure or deployment headroom explicitly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an interview, narrate the assumptions, show the arithmetic, identify the largest constraint, and explain what you would measure next. For a real design, record the inputs, source, confidence, and owner beside the estimate. A useful next step is to put the assumptions and capacity implications into a &lt;a href="https://letinix.com/resources/technical-design-doc-template" rel="noopener noreferrer"&gt;technical design document&lt;/a&gt;, where reviewers can challenge the numbers before they become infrastructure commitments.&lt;/p&gt;

&lt;p&gt;Use the &lt;a href="https://letinix.com/resources/system-design-cheat-sheet" rel="noopener noreferrer"&gt;System Design Cheat Sheet&lt;/a&gt; as the companion reference while practicing these calculations. The cheat sheet is the primary resource for this topic; this article explains the reasoning behind the estimates and how to connect them to architectural choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pml.nist.gov/cuu/Units/binary.html" rel="noopener noreferrer"&gt;Definitions of the SI units: The binary prefixes — National Institute of Standards and Technology&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/engineer-growth/back-of-the-envelope-system-design-estimation" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>interview</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>The AI Bubble Question Is About Timing, Not Demand</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 10 Nov 2026 04:45:18 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/the-ai-bubble-question-is-about-timing-not-demand-25ci</link>
      <guid>https://dev.to/mdazlaanzubair/the-ai-bubble-question-is-about-timing-not-demand-25ci</guid>
      <description>&lt;p&gt;Whether the AI bubble is popping is the wrong question to start with. The demand side of AI is real and still growing quickly. The risk is a timing mismatch: the largest AI companies and their cloud suppliers have committed to spending that is bigger than their current revenue, much of it can't be cancelled, and the bills arrive before the revenue they are betting on. If demand keeps compounding on schedule, the build-out pays off. If it arrives a year late, the losses land on whoever is holding the fixed costs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Figures in this article are as of November 9, 2026. Anthropic's IPO pricing and Nvidia's quarterly results are both expected in mid-November and may change the picture quickly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Demand is not the weak point.&lt;/strong&gt; Google Cloud revenue grew 103% year over year in Q3 2026, and Anthropic reported $17.0 billion of revenue in the same quarter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commitments are.&lt;/strong&gt; Anthropic's amended S-1 lists about $895 billion of compute and infrastructure commitments, with $69.8 billion due in the next 12 months, roughly equal to four times its latest quarterly revenue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The strain shows up in cash flow and financing first:&lt;/strong&gt; Alphabet's free cash flow turned negative for a second quarter, Oracle sold $10 billion of stock at a discount alongside $10 billion of new debt, and OpenAI cut its funding target by a third.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For builders,&lt;/strong&gt; the practical response is to stop assuming today's AI API prices and providers are stable inputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What changed in October 2026
&lt;/h2&gt;

&lt;p&gt;For most of the past two years, the AI investment story was told through rising valuations. In October and early November 2026, it started to show up in less flattering numbers.&lt;/p&gt;

&lt;p&gt;On October 29, Alphabet's Class A shares fell 12.6%, their worst day since they began trading more than 20 years ago, &lt;a href="https://fortune.com/2026/10/29/alphabet-stock-worst-day-sp-500-nasdaq-dow/" rel="noopener noreferrer"&gt;according to the Associated Press&lt;/a&gt;. About $500 billion of market value was erased, &lt;a href="https://www.entrepreneur.com/business-news/alphabet-just-lost-500-billion-in-one-day-heres-why-wall-street-is-spooked" rel="noopener noreferrer"&gt;per the Wall Street Journal's figure&lt;/a&gt;. Earnings and search revenue missed expectations, so AI spending was not the only cause, but negative free cash flow was a central part of the reaction.&lt;/p&gt;

&lt;p&gt;The same week, the Financial Times, Wall Street Journal and CNBC reported that OpenAI had lowered the target for its latest private round from up to $30 billion to about $20 billion, at a $1.25 trillion valuation instead of the $1.4 trillion it had sought (&lt;a href="https://fourweekmba.com/ai-openai-cuts-its-funding-target-to-about-20b-at-1-25t/" rel="noopener noreferrer"&gt;summary of the reports&lt;/a&gt;). The round had not closed when it was reported.&lt;/p&gt;

&lt;p&gt;On November 2, Oracle priced 86.2 million new shares at $116, about an 11% discount to the prior close, plus $10 billion of senior notes with coupons from 7.00% to 8.65% (&lt;a href="https://stockhub.kr/en/newswire/prn/302927244" rel="noopener noreferrer"&gt;Oracle's pricing announcement&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;And on October 13, the International Monetary Fund's Global Financial Stability Report named an AI-driven market correction as one of three salient risks to global financial stability (&lt;a href="https://thenextweb.com/news/imf-circular-ai-deals-financial-stability-report" rel="noopener noreferrer"&gt;coverage of the report&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;None of these events, alone, is a crash. Together they show investors shifting from asking whether AI demand exists to asking when today's spending pays for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demand is real
&lt;/h2&gt;

&lt;p&gt;The bubble framing often implies that the underlying product is hollow. The 2026 numbers don't support that.&lt;/p&gt;

&lt;p&gt;Google Cloud revenue reached $30.71 billion in Q3 2026, up from $15.16 billion a year earlier (&lt;a href="https://www.techloy.com/google-stock-down-alphabet-q3-earnings/" rel="noopener noreferrer"&gt;Alphabet's Q3 results, summarized by Techloy&lt;/a&gt;). Google Cloud's chief executive described "extraordinary demand" from AI labs, financial institutions and enterprises on the earnings call (&lt;a href="https://siliconangle.com/?p=852340" rel="noopener noreferrer"&gt;SiliconANGLE&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Anthropic's amended S-1 reports Q3 2026 revenue of $16.96 billion, up 1,127% year over year, after $16.3 billion in the first half of the year (&lt;a href="https://stockanalysis.com/news/anthropic-third-quarter-revenue-17-billion-ipo-filing/" rel="noopener noreferrer"&gt;StockAnalysis summary of the filing&lt;/a&gt;). More than 11,900 customers pay it at least $100,000 a year (&lt;a href="https://www.renaissancecapital.com/IPO-Center/News/122533/anthropic-discloses-third-quarter-financial-results-ahead-of-multibillion" rel="noopener noreferrer"&gt;Renaissance Capital&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;These are not the revenue lines of a technology nobody wants. If AI were a pure hype cycle, the argument would be simple. It isn't, which is why the more useful question is about timing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mismatch: commitments versus revenue
&lt;/h2&gt;

&lt;p&gt;The clearest public view of the timing problem is Anthropic's IPO filing, because it is the first frontier AI lab to disclose its obligations in an SEC document.&lt;/p&gt;

&lt;p&gt;The amended S-1 filed on November 2 lists approximately $895.4 billion of purchase commitments and lease agreements, which the company says relate substantially to compute and infrastructure (&lt;a href="https://fourweekmba.com/ai-anthropics-895b-compute-commitments-69-8b-due-in-a-year/" rel="noopener noreferrer"&gt;FourWeekMBA's reading of the S-1/A&lt;/a&gt;). About $69.8 billion falls due in the 12 months after September 30, and about $447.5 billion before the end of 2030 (&lt;a href="https://www.theregister.com/a/5307089" rel="noopener noreferrer"&gt;The Register&lt;/a&gt;). The deals with Microsoft, Google, Amazon and Broadcom are largely non-cancellable, and some require payment regardless of usage.&lt;/p&gt;

&lt;p&gt;The revenue side is shaped differently. Fortune's reading of the filing notes that much of Anthropic's revenue is consumption-based, and many contracts let customers reduce usage or terminate with limited notice (&lt;a href="https://fortune.com/2026/10/26/anthropics-s-1-makes-clear-its-on-the-hook-for-billions-in-compute-its-customers-can-walk-at-any-time-2/" rel="noopener noreferrer"&gt;Fortune&lt;/a&gt;). The company contracts compute 12 to 18 months in advance.&lt;/p&gt;

&lt;p&gt;Annualising Q3 revenue (4 × $16.96 billion) gives about $67.8 billion, slightly less than the $69.8 billion of commitments due over the same 12 months. That is a deliberately crude comparison: revenue is still growing, and commitments are not the company's only costs. It does show the shape of the bet. The obligations are sized for revenue that hasn't been booked yet.&lt;/p&gt;

&lt;p&gt;Anthropic's chief executive, Dario Amodei, described this risk himself in February. Explaining on the Dwarkesh Podcast why the company was not buying compute even more aggressively, he said that if his growth forecast is off by a year, or growth is 5x instead of 10x, "then you go bankrupt" (&lt;a href="https://fortune.com/2026/02/14/anthropic-ceo-dario-amodei-spending-capex-risk-ai-revenue-forecasts-bankruptcy" rel="noopener noreferrer"&gt;Fortune&lt;/a&gt;). That is the timing thesis in the words of someone with every incentive to be optimistic.&lt;/p&gt;

&lt;p&gt;Anthropic is the case with public numbers, not the only case. OpenAI has announced compute partnerships with Nvidia, Broadcom, Oracle and AMD, and the same logic applies to any company that commits to multi-year capacity against usage-based revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the strain shows up first
&lt;/h2&gt;

&lt;p&gt;Timing risk does not show up first as falling demand. It shows up in cash flow, in the cost of financing, and in projects that slip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cash flow.&lt;/strong&gt; Alphabet spent $51.36 billion on capital expenditure in Q3 2026, up from $23.95 billion a year earlier, and reported free cash flow of negative $9.07 billion after negative $5.86 billion in Q2 (&lt;a href="https://www.techloy.com/google-stock-down-alphabet-q3-earnings/" rel="noopener noreferrer"&gt;Techloy&lt;/a&gt;). It raised its 2026 capex guidance to $195 billion to $205 billion in July (&lt;a href="https://www.briefing.com/story-stocks/archive/2026/7/23/alphabet-slides-as-massive-ai-spending-increase-overshadows-strong-search-and-cloud-growth-%28goog%29" rel="noopener noreferrer"&gt;Briefing.com&lt;/a&gt;). Across Amazon, Microsoft, Alphabet, Meta and Oracle, 2026 capex is projected at roughly $803 billion to $828 billion (&lt;a href="https://www.storagenewsletter.com/?p=306454" rel="noopener noreferrer"&gt;StorageNewsletter&lt;/a&gt;). These companies can absorb negative quarters. Investors are now pricing how many more there will be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Financing.&lt;/strong&gt; Oracle is the case where the build-out leans most on borrowed money. Its debt stood at about $125 billion at the end of August 2026 (&lt;a href="https://political.org/2026/11/02/oracle-seeks-to-raise-20-billion-through-stock-and-debt-to-fund-ai-expansion/" rel="noopener noreferrer"&gt;Political.org, citing Oracle's filings&lt;/a&gt;). Its stock peaked at $345.72 in September 2025 after a 36% one-day jump on its AI backlog, then fell to $114.50 in late July 2026, down about 67% (&lt;a href="https://cbonds.hk/news/4050603/" rel="noopener noreferrer"&gt;Motley Fool via Cbonds&lt;/a&gt;). The November share sale and new bonds at 7% to 8.65% show what capital costs once the market is less sure of the payoff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Physical delivery.&lt;/strong&gt; Oracle's 2.45 GW Project Jupiter campus in New Mexico depends on a gas pipeline that state regulators have denied twice. Oracle sent a force majeure notice to the developer, a Blue Owl Capital unit, preserving the right to defer payments if the campus misses its 2028 target (&lt;a href="https://techcrunch.com/?p=3169077" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;). Oracle says the project remains on schedule. The notice still shows who carries the risk when power, permits or construction run late: the parties with fixed obligations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Circular financing makes timing errors spread
&lt;/h2&gt;

&lt;p&gt;A timing miss at one company would be manageable if the industry's money flows were independent. They aren't.&lt;/p&gt;

&lt;p&gt;The IMF report identified about $300 billion of equity transactions from hyperscalers into weaker AI firms over three years, about $650 billion of related debt, and about $1.4 trillion of future revenue commitments, and flagged these circular arrangements as a channel that could deepen a correction (&lt;a href="https://techjacksolutions.com/?p=96262" rel="noopener noreferrer"&gt;coverage of the report&lt;/a&gt;). A Bank for International Settlements bulletin published on October 1 mapped the same overlap of investment and commercial relationships across more than 1,200 AI firms (&lt;a href="https://www.bis.org/publications/bulletin-137-circular-relationships-among-ai-firms.pdf" rel="noopener noreferrer"&gt;BIS Bulletin No. 137&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The mechanism matters for the timing argument. When an investor is also the supplier, demand and investment are partly the same money. Backlog can look strong while depending on the customer's next funding round. If one lab's revenue arrives late, the effect passes to its cloud provider's backlog, that provider's debt, and its chip orders.&lt;/p&gt;

&lt;h2&gt;
  
  
  The depreciation assumption underneath
&lt;/h2&gt;

&lt;p&gt;There is one more timing assumption buried in the accounting. Between 2020 and 2023, the large cloud providers extended the useful life of their servers from three or four years to about six, which spreads the cost of each server over more years and raises reported profit (&lt;a href="https://siliconangle.com/2025/11/22/resetting-gpu-depreciation-ai-factories-bend-dont-break-useful-life-assumptions/" rel="noopener noreferrer"&gt;SiliconANGLE&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Critics argue that AI accelerators turn over every two to three years, so six-year lives overstate earnings. Defenders, including Bernstein, argue that older GPUs move to inference and cheaper workloads and keep earning. In 2025, Amazon shortened the useful life of a subset of its servers from six years back to five, citing the pace of AI hardware development, while Meta lengthened some to 5.5 (&lt;a href="https://www.advisorperspectives.com/articles/2025/11/12/ai-bubbleignoring-michael-burrys-fears" rel="noopener noreferrer"&gt;Advisor Perspectives&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Neither side has settled this, and it does not need to be settled for the thesis to hold. If the useful life of today's hardware is shorter than the books assume, the window for revenue to catch up is shorter too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The strongest counterarguments
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Demand is outrunning supply, not the other way around.&lt;/strong&gt; In July, Google said it would rely on higher-cost third-party capacity to serve very large cloud customers while its own capacity ramps up (&lt;a href="https://www.briefing.com/story-stocks/archive/2026/7/23/alphabet-slides-as-massive-ai-spending-increase-overshadows-strong-search-and-cloud-growth-%28goog%29" rel="noopener noreferrer"&gt;Briefing.com&lt;/a&gt;). If that persists, today's capacity is not overbuilt, and the timing risk sits further out than the bears assume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The leading lab is already generating cash.&lt;/strong&gt; &lt;a href="https://www.renaissancecapital.com/IPO-Center/News/122533/anthropic-discloses-third-quarter-financial-results-ahead-of-multibillion" rel="noopener noreferrer"&gt;Renaissance Capital&lt;/a&gt; reports that Anthropic's operating cash flow turned positive at $6.6 billion, from negative $2.0 billion a year earlier, and that it held $95.6 billion of cash and $36 billion of short-term investments at September 30. About $213.8 billion of its commitments are subject to termination rights or conditions (&lt;a href="https://fourweekmba.com/ai-anthropics-895b-compute-commitments-69-8b-due-in-a-year/" rel="noopener noreferrer"&gt;FourWeekMBA&lt;/a&gt;). A company in that position has more room to absorb a slower year than the headline commitment figure suggests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Headline losses overstate the problem.&lt;/strong&gt; Anthropic's reported net loss for the first nine months of 2026 is about $104 billion (&lt;a href="https://www.idlen.io/news/anthropic-amended-s1-q3-2026-17-billion-revenue-compute-claude-developers/" rel="noopener noreferrer"&gt;Idlen&lt;/a&gt;), but most of it is a non-cash charge from revaluing convertible notes as the company's valuation rose (&lt;a href="https://techspot.com/news/114341-anthropic-files-go-public-could-biggest-ipo-ever.html" rel="noopener noreferrer"&gt;TechSpot&lt;/a&gt;). Its Q3 operating loss was $567 million. A viral claim that the company "barely makes money" does not hold up against its own filing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overbuilt infrastructure has been useful before.&lt;/strong&gt; Fiber laid during the dot-com boom carried the internet's next decade. The counterpoint is that fiber stays useful for decades, while accelerators lose competitiveness much faster, which brings the argument back to depreciation.&lt;/p&gt;

&lt;p&gt;These points narrow the thesis rather than refute it. They suggest that a correction, if it comes, is more likely to look like financing stress, delayed projects and repricing than like collapsing demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for builders
&lt;/h2&gt;

&lt;p&gt;A financial correction in AI would not mean the technology stops working. After the dot-com crash, the infrastructure and many of the products survived, and useful companies were built on what was left. For engineers and teams shipping AI features, the practical implications are narrower:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Treat API pricing as a variable, not a constant.&lt;/strong&gt; Prices could rise if providers need margin, or fall further under competition. Anthropic's filing explicitly flags the risk of being forced to cut token prices (&lt;a href="https://fortune.com/2026/10/26/anthropics-s-1-makes-clear-its-on-the-hook-for-billions-in-compute-its-customers-can-walk-at-any-time-2/" rel="noopener noreferrer"&gt;Fortune&lt;/a&gt;). Design so your unit economics survive either direction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid a single-provider dependency for core features.&lt;/strong&gt; A provider under financial pressure can change pricing, rate limits or model availability quickly. An abstraction over two providers, or an open-weight fallback, is cheaper to build before you need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in cost engineering now.&lt;/strong&gt; Caching, prompt and context reduction, routing simple requests to smaller models, and measuring cost per task are useful whether or not prices move.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be skeptical of products that only work at today's prices.&lt;/strong&gt; Thin wrappers whose margin depends on current token pricing are the most exposed if that pricing changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure outcomes, not adoption.&lt;/strong&gt; MIT NANDA's 2025 report found that 95% of the organizations it studied saw no measurable return from generative AI, with the successful 5% tied to specific workflows (&lt;a href="https://campustechnology.com/articles/2025/08/26/mit-report-most-organizations-see-no-business-return-on-gen-ai-investments.aspx?p=1" rel="noopener noreferrer"&gt;Campus Technology&lt;/a&gt;). It is a preliminary study with a small sample, but the lesson about measurable outcomes holds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a closer look at what the productivity evidence actually shows, see &lt;a href="https://letinix.com/articles/analyze/ai-coding-productivity-research" rel="noopener noreferrer"&gt;AI coding tools and productivity: what the research actually found&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The evidence as of November 2026 supports a narrower claim than "the AI bubble is popping." Demand for AI is real and growing. The fragile part is the calendar: multi-year, largely non-cancellable compute commitments sized for revenue that has not arrived yet, financed partly through circular deals and partly through debt, on hardware whose useful life is contested.&lt;/p&gt;

&lt;p&gt;If growth continues at anything like 2026 rates, most of today's commitments will look reasonable in hindsight. If growth slows or slips by a year, the losses fall on whoever holds the fixed costs, and the effects travel through suppliers and lenders. The next useful data points are Anthropic's IPO pricing, Nvidia's mid-November results, and whether hyperscaler free cash flow recovers in early 2027.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.sec.gov/Archives/edgar/data/0002130357/000162828026067168/anthropicpbc-sx1.htm" rel="noopener noreferrer"&gt;Anthropic, PBC Form S-1 (October 26, 2026) — SEC EDGAR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stockanalysis.com/news/anthropic-third-quarter-revenue-17-billion-ipo-filing/" rel="noopener noreferrer"&gt;Anthropic's amended IPO filing shows Q3 revenue of $17.0B — StockAnalysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.renaissancecapital.com/IPO-Center/News/122533/anthropic-discloses-third-quarter-financial-results-ahead-of-multibillion" rel="noopener noreferrer"&gt;Anthropic discloses third quarter financial results ahead of IPO — Renaissance Capital&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.idlen.io/news/anthropic-amended-s1-q3-2026-17-billion-revenue-compute-claude-developers/" rel="noopener noreferrer"&gt;Anthropic's amended S-1: $17 billion in Q3 revenue — Idlen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techspot.com/news/114341-anthropic-files-go-public-could-biggest-ipo-ever.html" rel="noopener noreferrer"&gt;Anthropic files to go public, could be biggest IPO ever — TechSpot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fourweekmba.com/ai-anthropics-895b-compute-commitments-69-8b-due-in-a-year/" rel="noopener noreferrer"&gt;Anthropic's $895B compute commitments: $69.8B due in a year — FourWeekMBA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.theregister.com/a/5307089" rel="noopener noreferrer"&gt;Anthropic's compute tab could top $1T — The Register&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortune.com/2026/10/26/anthropics-s-1-makes-clear-its-on-the-hook-for-billions-in-compute-its-customers-can-walk-at-any-time-2/" rel="noopener noreferrer"&gt;Anthropic's S-1 makes clear it's on the hook for billions in compute — Fortune&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortune.com/2026/02/14/anthropic-ceo-dario-amodei-spending-capex-risk-ai-revenue-forecasts-bankruptcy" rel="noopener noreferrer"&gt;Dario Amodei explains his spending caution — Fortune&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortune.com/2026/10/29/alphabet-stock-worst-day-sp-500-nasdaq-dow/" rel="noopener noreferrer"&gt;Alphabet's stock has worst day in over 20 years — Fortune / Associated Press&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.techloy.com/google-stock-down-alphabet-q3-earnings/" rel="noopener noreferrer"&gt;Google stock down after Alphabet Q3 earnings — Techloy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://siliconangle.com/?p=852340" rel="noopener noreferrer"&gt;Alphabet's stock sinks after top-and-bottom line miss — SiliconANGLE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.briefing.com/story-stocks/archive/2026/7/23/alphabet-slides-as-massive-ai-spending-increase-overshadows-strong-search-and-cloud-growth-%28goog%29" rel="noopener noreferrer"&gt;Alphabet slides as AI spending increase overshadows growth — Briefing.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.entrepreneur.com/business-news/alphabet-just-lost-500-billion-in-one-day-heres-why-wall-street-is-spooked" rel="noopener noreferrer"&gt;Alphabet just lost $500 billion in one day — Entrepreneur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fourweekmba.com/ai-openai-cuts-its-funding-target-to-about-20b-at-1-25t/" rel="noopener noreferrer"&gt;OpenAI cuts its funding target to about $20B at $1.25T — FourWeekMBA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stockhub.kr/en/newswire/prn/302927244" rel="noopener noreferrer"&gt;Oracle announces pricing of $20 billion of common stock and senior notes — PR Newswire via StockHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://political.org/2026/11/02/oracle-seeks-to-raise-20-billion-through-stock-and-debt-to-fund-ai-expansion/" rel="noopener noreferrer"&gt;Oracle seeks to raise $20 billion through stock and debt — Political.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cbonds.hk/news/4050603/" rel="noopener noreferrer"&gt;Oracle one year after its record high — Motley Fool via Cbonds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/?p=3169077" rel="noopener noreferrer"&gt;Oracle sends force majeure notice on its New Mexico Stargate data center — TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.storagenewsletter.com/?p=306454" rel="noopener noreferrer"&gt;Anthropic files S-1 with the SEC; hyperscaler capex outlook — StorageNewsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thenextweb.com/news/imf-circular-ai-deals-financial-stability-report" rel="noopener noreferrer"&gt;IMF warns $1.4tn in circular AI deals could deepen a market correction — The Next Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techjacksolutions.com/?p=96262" rel="noopener noreferrer"&gt;IMF names AI share crash a salient risk — TechJack Solutions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bis.org/publications/bulletin-137-circular-relationships-among-ai-firms.pdf" rel="noopener noreferrer"&gt;BIS Bulletin No. 137: Circular relationships among AI firms — Bank for International Settlements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://siliconangle.com/2025/11/22/resetting-gpu-depreciation-ai-factories-bend-dont-break-useful-life-assumptions/" rel="noopener noreferrer"&gt;Resetting GPU depreciation — SiliconANGLE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.advisorperspectives.com/articles/2025/11/12/ai-bubbleignoring-michael-burrys-fears" rel="noopener noreferrer"&gt;AI bubble: ignoring Michael Burry's fears — Advisor Perspectives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://campustechnology.com/articles/2025/08/26/mit-report-most-organizations-see-no-business-return-on-gen-ai-investments.aspx?p=1" rel="noopener noreferrer"&gt;MIT report: most organizations see no business return on GenAI — Campus Technology&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/analyze/ai-bubble-timing-not-demand" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloud</category>
      <category>startup</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Write a Technical Design Doc That Gets a Decision</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:00:00 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/how-to-write-a-technical-design-doc-that-gets-a-decision-3mnc</link>
      <guid>https://dev.to/mdazlaanzubair/how-to-write-a-technical-design-doc-that-gets-a-decision-3mnc</guid>
      <description>&lt;p&gt;A technical design doc helps a team decide what to build, why it matters, and which trade-offs to accept. It is not a place to document every implementation detail before the direction is agreed.&lt;/p&gt;

&lt;p&gt;When a document gets no response, reviewers may not know what you need. When discussion jumps to minor implementation choices, the proposal may have described a solution before proving the problem. Write it as a decision proposal: lead with the question, support the problem with evidence, compare credible options, and state the decision required.&lt;/p&gt;

&lt;p&gt;This guide offers a practical structure and a clearly hypothetical example. Adapt the depth to the change; this is not a universal company process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a technical design doc is for
&lt;/h2&gt;

&lt;p&gt;A technical design document is a proposal for a technical change. It gives affected people enough context to evaluate the problem, challenge assumptions, and decide before implementation creates expensive commitments.&lt;/p&gt;

&lt;p&gt;A useful design doc supports three outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alignment before code:&lt;/strong&gt; expose missing requirements and disagreements while the design can still change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A record of reasoning:&lt;/strong&gt; preserve why an option was selected and which constraints mattered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A decision mechanism:&lt;/strong&gt; state what is being approved, who decides, and when.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A detailed design can still fail if it does not explain why the change is needed, which alternatives were considered, or what reviewers must approve.&lt;/p&gt;

&lt;p&gt;Google's &lt;a href="https://google.github.io/styleguide/docguide/best_practices.html" rel="noopener noreferrer"&gt;documentation guidance&lt;/a&gt; describes design docs and PRDs as documents used to collect feedback on a proposed implementation, then retained as archives of decisions after implementation. Google's &lt;a href="https://docs.cloud.google.com/architecture/architecture-decision-records" rel="noopener noreferrer"&gt;Architecture Decision Records guidance&lt;/a&gt; separately describes capturing options, requirements, decisions, and reasons. These are public examples of useful practices, not a claim that every team follows the same process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the decision, not the solution
&lt;/h2&gt;

&lt;p&gt;Before writing the architecture section, complete this sentence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We need a decision on whether to [specific choice] so that [intended outcome], by [date].&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then identify three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What is being decided?&lt;/strong&gt; State the actual choice: approve a migration, select a storage pattern, change an API boundary, introduce a queue, or keep the current design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who decides?&lt;/strong&gt; Name the decision owner or accountable group. Invite other people because they own affected systems, requirements, security, operations, or product constraints—not simply because they are senior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;By when?&lt;/strong&gt; Give reviewers a realistic deadline and explain the dependency. A date tied to a planned implementation milestone is more useful than an unexplained “ASAP.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you cannot answer these questions, do more discovery first. Do not ask reviewers to infer the decision from a long document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hypothetical example:&lt;/strong&gt; An engineering team sees intermittent timeouts while generating monthly customer exports. The engineer proposes moving export generation to a background worker. The decision is not “review my worker architecture.” It is: “Should we move exports to an asynchronous job flow, or first optimize the existing request path? We need the backend lead and service owner to decide by 14 May so implementation can be planned for the next cycle.” The roles and date are illustrative, not a real team process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sections that make a design doc useful
&lt;/h2&gt;

&lt;p&gt;A design doc does not need a large template for every change. A small refactor may need a short proposal; a cross-service migration or security-sensitive change may need more context, diagrams, and operational detail. Include the sections that help reviewers evaluate the decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Context and problem: show what is happening
&lt;/h3&gt;

&lt;p&gt;Describe the current state and the problem that makes a change worth considering. Be specific about who or what is affected, when the issue occurs, and what happens if the team does nothing.&lt;/p&gt;

&lt;p&gt;Use inspectable evidence: metrics with units and time windows, incident reports, support tickets, traces or logs, system constraints, and concrete user scenarios.&lt;/p&gt;

&lt;p&gt;Avoid vague statements such as “the architecture does not scale.” Name the observed constraint, such as requests timing out when generation exceeds a deadline. Include counts or impact estimates only when your data supports them; label incomplete evidence clearly.&lt;/p&gt;

&lt;p&gt;For the export example, attach timeout data, incident or ticket references, and the current request flow. If unavailable, label the failure pattern an initial report, not a confirmed trend.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Goals and non-goals: define the boundary
&lt;/h3&gt;

&lt;p&gt;Goals describe success. Prefer measurable outcomes with a known baseline: for example, a completion rate, processing-time target, latency budget, or reliability objective. Include the measurement window and source.&lt;/p&gt;

&lt;p&gt;Do not invent targets because a template has a number-shaped blank. If the baseline is unknown, make baseline collection part of the proposal or label the target as an open decision.&lt;/p&gt;

&lt;p&gt;Non-goals prevent scope creep. For the export example, goals might be completing long-running exports without holding an HTTP request open and exposing job status. Non-goals might include redesigning reporting or changing export formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Proposed design: explain the shape before the details
&lt;/h3&gt;

&lt;p&gt;Start with a system overview a reviewer can understand quickly. Describe the main components, their responsibilities, and the path of data or control between them. A simple diagram is often more useful than several paragraphs of component names.&lt;/p&gt;

&lt;p&gt;For the hypothetical proposal, the overview could show:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client submits an export request.&lt;/li&gt;
&lt;li&gt;The API validates it and creates a job.&lt;/li&gt;
&lt;li&gt;A worker claims the job and generates the file.&lt;/li&gt;
&lt;li&gt;The result is stored and the job status is updated.&lt;/li&gt;
&lt;li&gt;The client checks status and retrieves the completed export.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Explain only decision-relevant details: job ownership, retries, idempotency, storage lifecycle, access control, failure handling, observability, and API changes. Move lower-level details to implementation tasks.&lt;/p&gt;

&lt;p&gt;Use capacity estimates when scale changes the architecture. State assumptions such as request volume, payload size, processing duration, concurrency, retention, and expected growth. Show the calculation instead of dropping an unexplained number into the doc. The &lt;a href="https://letinix.com/resources/system-design-cheat-sheet" rel="noopener noreferrer"&gt;Letinix System Design Cheat Sheet&lt;/a&gt; can help organize estimation inputs and system building blocks; validate its reference figures against your own workload rather than treating them as service measurements.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Alternatives: include the simplest fix and doing nothing
&lt;/h3&gt;

&lt;p&gt;Do not explain only the preferred design. Show what else could solve the problem and why it may be less suitable.&lt;/p&gt;

&lt;p&gt;At minimum, compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do nothing:&lt;/strong&gt; what happens if the team accepts the current behavior? Is the cost tolerable, or does the risk continue?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The simplest fix:&lt;/strong&gt; could a timeout adjustment, query optimization, pagination, caching, or a bounded change solve the actual problem?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The proposed approach:&lt;/strong&gt; what does it improve, and what complexity does it introduce?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other credible options:&lt;/strong&gt; include alternatives that meet the requirements and are realistic for the team to implement or operate.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Benefits&lt;/th&gt;
&lt;th&gt;Costs and risks&lt;/th&gt;
&lt;th&gt;When it may fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keep the synchronous flow&lt;/td&gt;
&lt;td&gt;No new job infrastructure&lt;/td&gt;
&lt;td&gt;Long requests can still fail; request capacity remains occupied&lt;/td&gt;
&lt;td&gt;Impact is low or the issue is temporary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optimize the current path&lt;/td&gt;
&lt;td&gt;Smallest architectural change&lt;/td&gt;
&lt;td&gt;Does not remove request-duration limits if work remains long-running&lt;/td&gt;
&lt;td&gt;Profiling identifies a clear bottleneck&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use a background job flow&lt;/td&gt;
&lt;td&gt;Separates request handling from long-running work&lt;/td&gt;
&lt;td&gt;Adds job state, retries, worker operations, and status handling&lt;/td&gt;
&lt;td&gt;Asynchronous completion is a requirement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is illustrative. A real proposal should compare options that fit the actual system and evidence. Avoid straw-man alternatives that exist only to make the preferred solution look inevitable.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Risks, rollout, and rollback: explain how change stays controlled
&lt;/h3&gt;

&lt;p&gt;List specific failure modes and how the team will detect or contain them. Avoid generic labels such as “performance, security, and scalability.”&lt;/p&gt;

&lt;p&gt;For a background export flow, ask whether duplicate job delivery can create duplicate exports, what happens when a worker crashes mid-file, whether users can access another customer's export, how stuck jobs are detected, how long completed files are retained, and what happens if the queue or storage is unavailable.&lt;/p&gt;

&lt;p&gt;Describe a staged rollout. Identify the first cohort or traffic slice, the signals that determine whether rollout can continue, and who watches those signals. Define rollback in operational terms: which switch, deployment, or routing change returns the system to the previous behavior? What happens to jobs already in progress? A rollback plan that ignores partially processed work is incomplete.&lt;/p&gt;

&lt;p&gt;For data migrations, include compatibility and recovery details. State whether old and new versions can run together, whether writes are reversible, and what data may need reconciliation. If rollback becomes unsafe after a particular step, identify that point explicitly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write for reviewers who skim
&lt;/h2&gt;

&lt;p&gt;Reviewers will scan before they read closely. Make the scan useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write the summary last.&lt;/strong&gt; Once the problem, goals, design, alternatives, and risks are stable, write a short summary containing the problem, proposed option, most important trade-off, requested decision, and deadline. Do not use it to introduce claims the body does not support.&lt;/p&gt;

&lt;p&gt;Use headings that communicate the point. “Why large exports time out” is more informative than “Background.” A diagram should show the current or proposed flow, boundaries, and important failure paths—not decorative boxes. Tables help compare alternatives, requirements, and rollout criteria.&lt;/p&gt;

&lt;p&gt;Cut anything that does not help the reviewer understand the problem, evaluate the options, or make the decision. Move detailed API contracts, field-by-field schemas, exhaustive test cases, and implementation tickets into linked supporting material when they are not central to the architecture choice. Keep the proposal focused; link to details rather than duplicating them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run the review as a process, not a broadcast
&lt;/h2&gt;

&lt;p&gt;A shared document link is not a review plan. Choose reviewers based on ownership and risk. Invite the decision owner, owners of affected systems and APIs, service operators, and relevant security, privacy, data, product, or support partners.&lt;/p&gt;

&lt;p&gt;Ask reviewers to assess the areas they own: operations, authorization and data exposure, or user-facing behavior.&lt;/p&gt;

&lt;p&gt;Use asynchronous comments for bounded proposals reviewers can assess independently. Set a deadline and ask focused questions. Meet when trade-offs remain unresolved, requirements conflict, or dependencies need joint discussion. The meeting should resolve issues, not replace the proposal.&lt;/p&gt;

&lt;p&gt;End the review with a recorded outcome: &lt;strong&gt;accepted, rejected, deferred, or accepted with conditions&lt;/strong&gt;. Capture the decision owner, date, rationale, unresolved conditions, and follow-up actions. Public engineering references show different ways to do this. &lt;a href="https://flutter.googlesource.com/mirrors/flutter.git/%2B/HEAD/docs/contributing/Design-Documents.md" rel="noopener noreferrer"&gt;Flutter's published RFC guidance&lt;/a&gt; describes asynchronous approval on the RFC pull request, with meetings used for discussion. &lt;a href="https://handbook.gitlab.com/handbook/engineering/architecture/workflow/" rel="noopener noreferrer"&gt;GitLab's public architecture workflow&lt;/a&gt; recommends documenting context, benefits, trade-offs, alternatives, and the reason for the selected decision. Treat these as examples to adapt, not policies to assume at your company.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short list of review questions
&lt;/h2&gt;

&lt;p&gt;Add questions that expose the uncertainties you need reviewers to address:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the problem supported by evidence, and is the impact described accurately?&lt;/li&gt;
&lt;li&gt;Are the goals measurable and the non-goals clear?&lt;/li&gt;
&lt;li&gt;Does the proposed design satisfy the stated requirements?&lt;/li&gt;
&lt;li&gt;Have we compared the simplest fix and the option of doing nothing?&lt;/li&gt;
&lt;li&gt;Which assumption, dependency, or failure mode could change the recommendation?&lt;/li&gt;
&lt;li&gt;Can the change be rolled out gradually and rolled back safely?&lt;/li&gt;
&lt;li&gt;Who owns the decision, and what must be true before implementation begins?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid asking reviewers to “share any thoughts.” A specific question gives them a place to start and helps distinguish a blocking concern from a preference.&lt;/p&gt;

&lt;h2&gt;
  
  
  After approval: preserve the decision and update the design
&lt;/h2&gt;

&lt;p&gt;Approval is not the document's endpoint. Record the decision, rationale, and conditions. If implementation diverges, update the design or link to a follow-up record so it does not misdescribe the system.&lt;/p&gt;

&lt;p&gt;Separate the proposal from the decision record when a choice deserves a durable, independently discoverable history. An Architecture Decision Record (ADR) can capture a specific architectural choice, its context, consequences, and alternatives. Google's &lt;a href="https://docs.cloud.google.com/architecture/architecture-decision-records" rel="noopener noreferrer"&gt;public ADR overview&lt;/a&gt; describes recording options, requirements, the decision, and reasons, and retaining the history when a decision changes. GitLab's &lt;a href="https://handbook.gitlab.com/handbook/engineering/architecture/workflow/" rel="noopener noreferrer"&gt;architecture workflow&lt;/a&gt; also describes using ADRs to record decisions and linking them from the main design document.&lt;/p&gt;

&lt;p&gt;Do not silently overwrite the original reasoning when a decision changes. Record what changed, why the old decision no longer fits, and which new constraints or evidence drove the revision. Keep links between the proposal, decision record, implementation, and relevant operational documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do next
&lt;/h2&gt;

&lt;p&gt;A strong design doc does not need to be long. It needs to make the problem legible, the options comparable, the risks visible, and the requested decision unmistakable.&lt;/p&gt;

&lt;p&gt;If you are starting from a blank page, use the free &lt;a href="https://letinix.com/resources/technical-design-doc-template" rel="noopener noreferrer"&gt;Letinix Technical Design Doc Template&lt;/a&gt;. It gives you a structured starting point for presenting a system change, showing supporting evidence, and asking reviewers for a clear decision. Adapt the sections to the scope of your proposal rather than filling every heading mechanically.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://google.github.io/styleguide/docguide/best_practices.html" rel="noopener noreferrer"&gt;Documentation Best Practices — Google Style Guides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.cloud.google.com/architecture/architecture-decision-records" rel="noopener noreferrer"&gt;Architecture Decision Records Overview — Google Cloud Architecture Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://handbook.gitlab.com/handbook/engineering/architecture/workflow/" rel="noopener noreferrer"&gt;Architecture Design Workflow — GitLab Handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://flutter.googlesource.com/mirrors/flutter.git/%2B/HEAD/docs/contributing/Design-Documents.md" rel="noopener noreferrer"&gt;Flutter RFCs &amp;amp; Design Documents — Flutter contributor documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/engineer-growth/write-technical-design-doc" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>architecture</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>How to Budget Retrieved Context in a RAG Pipeline</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Fri, 06 Nov 2026 19:00:00 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/how-to-budget-retrieved-context-in-a-rag-pipeline-5g3n</link>
      <guid>https://dev.to/mdazlaanzubair/how-to-budget-retrieved-context-in-a-rag-pipeline-5g3n</guid>
      <description>&lt;p&gt;A useful RAG token budget starts with the complete request, not just the retrieved passages. Reserve capacity for system instructions, the user query, conversation history, retrieval metadata and formatting, and the model’s output allowance. The remaining space is the maximum available for retrieved context—and it should be treated as a ceiling, not a target that every request must fill.&lt;/p&gt;

&lt;p&gt;There is no universal chunk size or top-k value that works for every retrieval-augmented generation (RAG) workload. Choose chunking and retrieval settings based on your model’s limits, document structure, query patterns, relevance, answer quality, and latency or cost constraints. Then measure the assembled request with the tokenizer or request-counting API for the model you actually call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculate the budget before retrieval
&lt;/h2&gt;

&lt;p&gt;Start with the model’s documented context capacity and output constraints. The exact relationship varies by model and API: some limits share a total context budget, while others describe input and output separately. Confirm the model’s current documentation rather than assuming every provider exposes limits in the same way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;retrieval_budget = context_limit
                 - instructions_and_query
                 - conversation_history
                 - formatting_and_metadata
                 - reserved_output
                 - safety_margin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a planning model, not a substitute for the API’s actual validation rules. If your provider defines separate input and output limits, enforce both. If tools, images, or structured message boundaries add tokens, count them through the provider’s supported request-level method where possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjn7132knzjt8dt9thc1o.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjn7132knzjt8dt9thc1o.webp" alt="A conceptual RAG context budget split into instruction and query overhead, retrieved passages, output reserve, and safety margin." width="799" height="465"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Conceptual allocation only; actual limits depend on the model and API.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Measure the request you will actually send
&lt;/h2&gt;

&lt;p&gt;A retrieved document chunk is not always the same string that reaches the model. The application may add a source title, URL, document ID, rank, access-control metadata, separators, instructions, or a citation wrapper. Those fields can be useful, but they also consume input capacity.&lt;/p&gt;

&lt;p&gt;Count the final serialized context after the application has assembled these parts. Counting each chunk in isolation is useful for filtering candidates, but it cannot account for repeated wrappers, query text, chat history, or message structure.&lt;/p&gt;

&lt;p&gt;Use the &lt;a href="https://letinix.com/tools/token-calculator" rel="noopener noreferrer"&gt;Letinix Token Calculator&lt;/a&gt; for a quick text-only inspection. It provides exact counts for the o200k_base and cl100k_base encodings and a character-based estimate for other selected models. For a production request, use the target provider’s request-counting API when it supports the inputs you send, and compare the count with actual usage reported by completed requests.&lt;/p&gt;
&lt;h2&gt;
  
  
  Treat chunk size and retrieval count as separate decisions
&lt;/h2&gt;

&lt;p&gt;Chunk size determines how much source material is grouped into each retrieval unit. Retrieval count determines how many candidates are selected. They interact, but changing both at once makes it harder to identify why quality or cost changed.&lt;/p&gt;

&lt;p&gt;Small chunks can make retrieval more specific but may separate a claim from the context needed to interpret it. Large chunks can preserve surrounding context but may include irrelevant passages and consume more of the prompt budget. Overlap may preserve information near boundaries, but it can also repeat text across retrieved chunks.&lt;/p&gt;

&lt;p&gt;The right values depend on the corpus and the question. A policy manual, API reference, source-code repository, and conversational knowledge base have different structural boundaries and retrieval needs. Avoid treating a provider’s example configuration as a universal recommendation.&lt;/p&gt;

&lt;p&gt;A controlled evaluation should vary one dimension at a time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Establish a baseline with the current chunking and retrieval settings.&lt;/li&gt;
&lt;li&gt;Change chunk size or overlap while holding the retrieval count and prompt constant.&lt;/li&gt;
&lt;li&gt;Measure retrieval relevance and answer quality on a representative query set.&lt;/li&gt;
&lt;li&gt;Change the retrieval count and evaluate again.&lt;/li&gt;
&lt;li&gt;Compare token use, latency, failure modes, and answer quality—not token reduction alone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Google’s Gemini File Search documentation, for example, exposes chunking configuration with maximum tokens per chunk and maximum overlap tokens. Those parameters are configuration options, not evidence that a particular setting is best for another corpus or model.&lt;/p&gt;
&lt;h2&gt;
  
  
  Select chunks under a token ceiling
&lt;/h2&gt;

&lt;p&gt;A fixed top-k retrieval step can return a set whose combined serialized size exceeds the available budget. A budget-aware assembly step should count candidates and include them only while the request remains within its limit.&lt;/p&gt;

&lt;p&gt;A simple greedy strategy can work as a first implementation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rag-budget.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pseudocode: countWithTargetModel must use the target model's tokenizer.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;countWithTargetModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;renderPrompt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;rankedChunks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;candidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderPrompt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;candidateTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;countWithTargetModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidateTokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;reservedOutput&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;safetyMargin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;contextLimit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;candidateTokens&lt;/span&gt;&lt;span class="p"&gt;;&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;This example illustrates a budget check; it is not a tested production implementation. In a real system, use the provider’s actual input/output constraint semantics, avoid repeatedly re-tokenizing the entire prompt when that becomes expensive, and preserve any required citation or permission metadata. A greedy fit check also does not guarantee that the selected chunks are the most useful combination: relevance, diversity, source coverage, recency, and redundancy may need to influence selection.&lt;/p&gt;

&lt;p&gt;If chunks are reordered or truncated after retrieval, retain source boundaries and enough provenance for citations. Never trim text blindly in a way that leaves a number, exception, code block, or claim without the qualification needed to interpret it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate the budget against answer quality
&lt;/h2&gt;

&lt;p&gt;The goal is not to maximize the number of tokens sent. It is to include enough relevant evidence to answer the query while avoiding unnecessary or redundant context.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieval quality: whether the needed source passages appear among candidates and selected chunks.&lt;/li&gt;
&lt;li&gt;Answer quality and grounding: whether the answer uses the retrieved evidence correctly and preserves qualifications.&lt;/li&gt;
&lt;li&gt;Context utilization: actual input tokens relative to the available input budget.&lt;/li&gt;
&lt;li&gt;Operational behavior: latency, request failures, truncation, and cost under realistic traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A smaller prompt is not necessarily a better RAG system if it drops decisive evidence. Likewise, a larger prompt is not automatically better if it adds duplicates or distractors. Token usage is one constraint in the evaluation, not the quality metric by itself.&lt;/p&gt;

&lt;p&gt;For cost-focused planning after you have measured representative input and output usage, use the &lt;a href="https://letinix.com/tools/llm-api-cost-calculator" rel="noopener noreferrer"&gt;LLM API Cost Calculator&lt;/a&gt;. It estimates spend from request volume and token counts; it does not replace a model-specific count or an evaluation of retrieval quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical implementation checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Confirm the target model’s context and output limits from its current documentation.&lt;/li&gt;
&lt;li&gt;Measure system instructions, query, history, metadata, and serialized retrieved passages—not only raw chunks.&lt;/li&gt;
&lt;li&gt;Keep output allowance and a safety margin separate from the retrieval budget.&lt;/li&gt;
&lt;li&gt;Tune chunk size, overlap, and retrieval count independently before testing combinations.&lt;/li&gt;
&lt;li&gt;Enforce a budget after retrieval, using a target-model-compatible counter or request-counting API.&lt;/li&gt;
&lt;li&gt;Evaluate relevance, grounding, quality, latency, and cost together on representative queries.&lt;/li&gt;
&lt;li&gt;Re-run the evaluation after changing the model, prompt template, corpus, chunker, or metadata format.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ai.google.dev/gemini-api/docs/tokens" rel="noopener noreferrer"&gt;Understand and count tokens — Gemini API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ai.google.dev/gemini-api/docs/file-search" rel="noopener noreferrer"&gt;File Search — Gemini API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.openai.com/api/docs/guides/token-counting" rel="noopener noreferrer"&gt;Counting tokens — OpenAI API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform.claude.com/docs/en/build-with-claude/token-counting" rel="noopener noreferrer"&gt;Token counting — Anthropic Claude Platform Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/rag-retrieved-context-token-budget" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>developer</category>
    </item>
    <item>
      <title>Why Token Counts Differ from Word Counts</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Wed, 04 Nov 2026 19:00:00 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/why-token-counts-differ-from-word-counts-4b25</link>
      <guid>https://dev.to/mdazlaanzubair/why-token-counts-differ-from-word-counts-4b25</guid>
      <description>&lt;p&gt;A word count cannot tell you exactly how many tokens an LLM will process. Token counts depend on the tokenizer or model family, the spelling and formatting of the text, and sometimes the structure of the API request around it. Rules such as “one token equals three-quarters of a word” are rough estimates for some English text—not a reliable conversion formula.&lt;/p&gt;

&lt;p&gt;If you need a useful count, measure the text with the tokenizer used by your target model. For OpenAI requests, tiktoken can count text using supported encodings; for a complete API request, use the provider’s token-counting API when available. The &lt;a href="https://letinix.com/tools/token-calculator" rel="noopener noreferrer"&gt;Letinix Token Calculator&lt;/a&gt; provides exact counts for its supported OpenAI encodings and labeled estimates for other models.&lt;/p&gt;

&lt;h2&gt;
  
  
  A word and a token measure different things
&lt;/h2&gt;

&lt;p&gt;A word count treats text as words according to a counting rule. A tokenizer divides text into units from a model’s vocabulary. Depending on the encoding, a token may represent a whole word, part of a word, punctuation, whitespace attached to text, or a short sequence of characters.&lt;/p&gt;

&lt;p&gt;Consider this illustrative text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Retry the request if status_code == 429.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A word counter might count the identifiers and punctuation according to its own splitting rules. A tokenizer instead applies its learned vocabulary and segmentation rules. It may represent status_code, 429, the equality operator, and surrounding spaces as several tokens or as fewer units. The exact result depends on the encoding; the example is not assigned a universal token count here.&lt;/p&gt;

&lt;p&gt;That is why word count, character count, and token count should be treated as separate measurements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ktptq9msomnkvlnhxmg.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ktptq9msomnkvlnhxmg.webp" alt="A conceptual comparison of word blocks, character marks, and token segments for one string; the boundaries are illustrative rather than a measured tokenizer output." width="799" height="465"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Illustrative only: token boundaries vary by encoding and text.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the same text can produce different token counts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The tokenizer matters
&lt;/h3&gt;

&lt;p&gt;Different model families use different token vocabularies and segmentation rules. Even within one provider, an encoding used by one model generation may differ from another.&lt;/p&gt;

&lt;p&gt;OpenAI’s maintained tiktoken library exposes named encodings and can map supported model names to an encoding with encoding_for_model(). Its documentation includes o200k_base and cl100k_base, among others. A count produced with one encoding is exact for that encoding; it is not automatically exact for another provider’s tokenizer.&lt;/p&gt;

&lt;p&gt;Anthropic and Google provide model-aware token-counting interfaces for their APIs. Use the provider’s own counting method when the result must match a request to that provider. A generic tokenizer from another ecosystem is not a substitute.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spelling, punctuation, and formatting matter
&lt;/h3&gt;

&lt;p&gt;Tokenization does not simply split at spaces. Capitalization, contractions, uncommon identifiers, repeated punctuation, numbers, and whitespace can change how a sequence is segmented. A familiar word may be represented compactly, while an unusual string may be divided into smaller pieces.&lt;/p&gt;

&lt;p&gt;This matters for prompts containing paths, version numbers, hashes, log lines, stack traces, source code, or JSON. A character-based rule of thumb can be useful for rough planning, but it can miss how technical strings are actually segmented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Language matters
&lt;/h3&gt;

&lt;p&gt;The relationship between words, characters, and tokens is not constant across languages. Word boundaries differ, scripts encode information differently, and a tokenizer’s vocabulary may represent some languages more efficiently than others. Do not carry an English-text estimate into multilingual content as though it were a guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  When is a token estimate good enough?
&lt;/h2&gt;

&lt;p&gt;Use the method that matches the decision you need to make.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Suitable method&lt;/th&gt;
&lt;th&gt;Important limitation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Roughly size a short English draft&lt;/td&gt;
&lt;td&gt;Character- or word-based estimate&lt;/td&gt;
&lt;td&gt;Not an exact tokenizer count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Count plain text for a supported OpenAI encoding&lt;/td&gt;
&lt;td&gt;Compatible tokenizer such as tiktoken&lt;/td&gt;
&lt;td&gt;Exact for that encoding, not necessarily the full API request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Count a request for a specific provider&lt;/td&gt;
&lt;td&gt;That provider’s token-counting API&lt;/td&gt;
&lt;td&gt;Check which request components the endpoint accepts and counts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify actual production usage&lt;/td&gt;
&lt;td&gt;Response usage fields&lt;/td&gt;
&lt;td&gt;Available after the request; field names vary by API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Choose a counting method based on the task and required accuracy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a quick first pass, paste the text into the &lt;a href="https://letinix.com/tools/token-calculator" rel="noopener noreferrer"&gt;Letinix Token Calculator&lt;/a&gt;. The tool’s current documentation says it computes exact counts for o200k_base and cl100k_base; for other selected models it estimates tokens as characters divided by four, rounded up. It processes up to 500,000 characters in the browser. Its non-OpenAI estimates can be substantially inaccurate, especially for code and non-English text.&lt;/p&gt;

&lt;p&gt;If your application depends on a hard limit, use a model-specific method instead of relying on a generic estimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plain-text counts are not complete API request counts
&lt;/h2&gt;

&lt;p&gt;A local tokenizer answers a narrow question: how does this text segment under this encoding? An API request can include additional structure, including message roles and boundaries, system instructions, tool definitions, schemas, images, files, or other multimodal content.&lt;/p&gt;

&lt;p&gt;For example, counting only the visible user prompt does not account for a system instruction or a JSON schema passed as a tool definition. The provider’s request-level counting endpoint is the better fit when you need to know how much input a structured request will consume. OpenAI documents a Responses API input-token counting endpoint; Anthropic’s token-counting endpoint accepts structured message inputs and supported tools and media; Google documents count_tokens for Gemini inputs.&lt;/p&gt;

&lt;p&gt;Even then, distinguish input tokens from output allowance and billed usage. A count of input tokens does not predict how many tokens the model will generate. Context limits and output limits are separate constraints, and some models also use internal reasoning tokens that affect usage. Check the documentation for the exact model and API endpoint you deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical workflow for developers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Choose the target model first. Do not estimate against a convenient tokenizer and assume the result transfers to another model family.&lt;/li&gt;
&lt;li&gt;Count the actual text you plan to send. Include the system prompt, retrieved passages, conversation history, and other text components you control.&lt;/li&gt;
&lt;li&gt;Count the structured request when possible. Use the provider’s token-counting endpoint for message structure, tools, images, files, or other supported inputs.&lt;/li&gt;
&lt;li&gt;Leave room for output and request overhead. A prompt that nearly fills a context window may leave too little space for generation or additional context.&lt;/li&gt;
&lt;li&gt;Compare with actual usage. Log provider-reported usage in representative requests and revisit assumptions when models, prompts, tools, or content types change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the next step, use the &lt;a href="https://letinix.com/tools/token-calculator" rel="noopener noreferrer"&gt;Letinix Token Calculator&lt;/a&gt; to inspect a text sample and compare its count across supported encodings. If your primary question is financial rather than tokenization or context fit, continue with the &lt;a href="https://letinix.com/tools/llm-api-cost-calculator" rel="noopener noreferrer"&gt;LLM API Cost Calculator&lt;/a&gt;, which estimates spend from expected request volume and input/output token counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.openai.com/api/docs/guides/token-counting" rel="noopener noreferrer"&gt;Counting tokens — OpenAI API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.openai.com/en/articles/4936856-understanding-and-counting-tokens" rel="noopener noreferrer"&gt;Understanding and counting tokens — OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openai/tiktoken" rel="noopener noreferrer"&gt;tiktoken — OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform.claude.com/docs/en/build-with-claude/token-counting" rel="noopener noreferrer"&gt;Token counting — Anthropic Claude Platform Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ai.google.dev/gemini-api/docs/tokens" rel="noopener noreferrer"&gt;Understand and count tokens — Gemini API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/why-token-counts-differ-from-word-counts" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>developer</category>
    </item>
    <item>
      <title>XML Tags vs. Markdown in LLM Prompts: When to Use Each</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 03 Nov 2026 09:40:38 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/xml-tags-vs-markdown-in-llm-prompts-when-to-use-each-3783</link>
      <guid>https://dev.to/mdazlaanzubair/xml-tags-vs-markdown-in-llm-prompts-when-to-use-each-3783</guid>
      <description>&lt;p&gt;Use Markdown headings for a readable default and XML-style tags when explicit content boundaries or nested structure help. Combine them when each does a different job—for example, Markdown for top-level instructions and XML tags around a supplied document. There is no universal winner: OpenAI documents both as useful ways to mark logical boundaries, while Anthropic recommends descriptive XML tags for complex prompts. Test the format against your model and task rather than treating syntax as a performance guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes between Markdown and XML tags?
&lt;/h2&gt;

&lt;p&gt;Markdown uses familiar headings, lists, and emphasis to organize instructions. XML-style tags wrap a section in an explicit opening and closing marker. Both can make prompt parts easier to distinguish, but they are not a security boundary and do not replace clear instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldsa1fmrvwj6r7y7mrp9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldsa1fmrvwj6r7y7mrp9.webp" alt="Comparison of equivalent prompt sections written with Markdown headings and XML-style tags." width="800" height="419"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two ways to mark prompt structure; choose based on readability and boundary clarity.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Markdown example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Task&lt;/span&gt;
Summarize the supplied document in three bullets.

&lt;span class="gu"&gt;## Context&lt;/span&gt;
The audience is a software engineering manager.

&lt;span class="gu"&gt;## Input&lt;/span&gt;
[DOCUMENT TEXT]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;XML-style example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;task&amp;gt;&lt;/span&gt;
Summarize the supplied document in three bullets.
&lt;span class="nt"&gt;&amp;lt;/task&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;context&amp;gt;&lt;/span&gt;
The audience is a software engineering manager.
&lt;span class="nt"&gt;&amp;lt;/context&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&amp;gt;&lt;/span&gt;
[DOCUMENT TEXT]
&lt;span class="nt"&gt;&amp;lt;/input&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These examples express the same intended organization. The choice is about how you want to express boundaries and maintain the prompt—not about choosing a magic syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Markdown is the better default
&lt;/h2&gt;

&lt;p&gt;Choose Markdown when the prompt is primarily a set of instructions that people need to read, review, and maintain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human-readable sections: headings like ## Task and ## Constraints are quick to scan in a code review.&lt;/li&gt;
&lt;li&gt;Lists of requirements: bullets make independent rules easy to inspect and edit.&lt;/li&gt;
&lt;li&gt;Simple prompt templates: a short task with a few sections may not benefit from additional opening and closing tags.&lt;/li&gt;
&lt;li&gt;Documentation and collaboration: Markdown is widely used in repositories, issue trackers, and internal docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a classification prompt with a clear task, a few decision rules, and a short output contract may be easiest to maintain as Markdown. Keep the structure proportional to the prompt; do not add headings simply to make a small instruction look more formal.&lt;/p&gt;

&lt;h2&gt;
  
  
  When XML-style tags are useful
&lt;/h2&gt;

&lt;p&gt;Use XML-style tags when the prompt contains multiple kinds of content that need explicit start and end boundaries, especially when some sections contain long or nested material.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;instructions&amp;gt;&lt;/span&gt;
Summarize the source. Use only facts supported by it.
&lt;span class="nt"&gt;&amp;lt;/instructions&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;source_document&amp;gt;&lt;/span&gt;
[UNTRUSTED DOCUMENT CONTENT]
&lt;span class="nt"&gt;&amp;lt;/source_document&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;output_requirements&amp;gt;&lt;/span&gt;
Return three bullet points and identify any missing information.
&lt;span class="nt"&gt;&amp;lt;/output_requirements&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it easier to see where the source begins and ends. Anthropic recommends descriptive, consistent tag names and nesting tags when the content has a natural hierarchy. OpenAI's guidance also describes XML tags as a way to delineate supporting documents and context data. The benefits are organizational; tags alone do not neutralize malicious instructions inside a document or guarantee that the model will follow the intended boundaries.&lt;/p&gt;

&lt;p&gt;XML-style tags are particularly useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The prompt includes a long source document or several documents.&lt;/li&gt;
&lt;li&gt;You need to distinguish instructions from quoted or user-provided content.&lt;/li&gt;
&lt;li&gt;A section has a natural hierarchy, such as a collection of documents and each document's metadata.&lt;/li&gt;
&lt;li&gt;You need clear boundaries around examples or variable input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use descriptive tag names that explain the content, such as &amp;lt;instructions&amp;gt;, &amp;lt;context&amp;gt;, &amp;lt;source_document&amp;gt;, and &amp;lt;output_requirements&amp;gt;. Consistency matters more than inventing a complicated tag vocabulary.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to combine Markdown and XML
&lt;/h2&gt;

&lt;p&gt;You do not have to choose one format for every part of a prompt. A practical hybrid uses Markdown for the top-level outline and XML-style tags for data boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Task&lt;/span&gt;
Summarize the supplied source in three bullets. Do not add facts that are absent from the source.

&lt;span class="gu"&gt;## Source&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;source_document&amp;gt;&lt;/span&gt;
[PASTE SOURCE TEXT HERE]
&lt;span class="nt"&gt;&amp;lt;/source_document&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Output format&lt;/span&gt;
Return exactly three bullets. If the source does not support a requested detail, say so.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Markdown headings make the overall task easy to scan. The XML tags mark the beginning and end of the source content. Use a hybrid only when it adds clarity; duplicated layers of headings and tags can make a prompt harder to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  A decision guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt situation&lt;/th&gt;
&lt;th&gt;Practical starting point&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Short task with a few rules&lt;/td&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;td&gt;Readable without extra syntax&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long source document&lt;/td&gt;
&lt;td&gt;XML tags around the source, with Markdown instructions if useful&lt;/td&gt;
&lt;td&gt;Makes the source boundary explicit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple related documents&lt;/td&gt;
&lt;td&gt;Nested XML-style tags plus concise top-level instructions&lt;/td&gt;
&lt;td&gt;Represents the hierarchy of inputs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt maintained by a team&lt;/td&gt;
&lt;td&gt;Whichever format is easiest to review consistently&lt;/td&gt;
&lt;td&gt;Reviewability is a maintenance requirement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model-specific workflow&lt;/td&gt;
&lt;td&gt;Follow the provider's current guidance, then evaluate&lt;/td&gt;
&lt;td&gt;Prompt behavior can differ across models and versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strict machine-readable output&lt;/td&gt;
&lt;td&gt;Use the provider's supported structured-output feature when available&lt;/td&gt;
&lt;td&gt;Prompt formatting alone is not schema enforcement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Practical starting points, not benchmark results.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a starting guide, not a benchmark result. The table summarizes the cited providers' guidance and a practical maintainability recommendation; it does not claim that one syntax is more accurate across all models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatting does not replace application safeguards
&lt;/h2&gt;

&lt;p&gt;A tagged input section can make a source boundary visible, but untrusted text may still contain instruction-like content. Do not rely on Markdown headings or XML tags as the only protection against prompt injection. Limit tool permissions, separate trusted instructions from untrusted data in the application design, validate outputs, and test realistic adversarial cases.&lt;/p&gt;

&lt;p&gt;Likewise, if your application needs JSON or another strict output shape, defining it in Markdown or XML is not the same as enforcing a schema. Use a supported structured-output feature where available and validate the result in your application. OpenAI distinguishes JSON mode from Structured Outputs in its Structured Outputs guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the choice with your actual task
&lt;/h2&gt;

&lt;p&gt;Do not evaluate syntax in the abstract. Keep the task, input, model, and success criteria stable while you compare versions.&lt;/p&gt;

&lt;p&gt;Write one baseline prompt using the format your team finds easiest to maintain.&lt;/p&gt;

&lt;p&gt;Create an alternative that changes only the boundaries or section markup—not the underlying instructions.&lt;/p&gt;

&lt;p&gt;Run both against representative normal, ambiguous, and edge-case inputs.&lt;/p&gt;

&lt;p&gt;Score outputs against explicit criteria, such as required fields, factual support, correct refusal or fallback behavior, and downstream parseability.&lt;/p&gt;

&lt;p&gt;Repeat on the model and deployment configuration you actually intend to use.&lt;/p&gt;

&lt;p&gt;Keep the clearer or better-performing version, record the decision, and rerun the checks after meaningful changes.&lt;/p&gt;

&lt;p&gt;If you already have prompt wording and only need to arrange it into Markdown headings, XML tags, or plain labels, use the Letinix Prompt Formatter. It organizes existing sections and can clean whitespace or quotation marks; it does not rewrite wording or prove that the resulting prompt is better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;Start with Markdown for a readable outline. Add XML-style tags where long or nested content needs explicit boundaries. Combine them when the two formats have distinct jobs, and keep the result as simple as the task allows. The only reliable way to choose for a production workflow is to evaluate representative inputs against criteria that matter to your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;OpenAI, Prompt engineering. Guidance on message formatting with Markdown and XML tags.&lt;/p&gt;

&lt;p&gt;Anthropic, Claude prompting best practices. Guidance on XML tags, descriptive names, and nested content.&lt;/p&gt;

&lt;p&gt;OpenAI, Structured Outputs. Guidance on schema-constrained output and related limitations.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/xml-tags-vs-markdown-in-llm-prompts" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>promptengineering</category>
      <category>software</category>
    </item>
    <item>
      <title>The Hardest Part of Starting a New Developer Job Is Understanding the Codebase</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Sat, 31 Oct 2026 14:39:28 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/the-hardest-part-of-starting-a-new-developer-job-is-understanding-the-codebase-52j4</link>
      <guid>https://dev.to/mdazlaanzubair/the-hardest-part-of-starting-a-new-developer-job-is-understanding-the-codebase-52j4</guid>
      <description>&lt;p&gt;You clear the interviews. You accept the offer. You finish the paperwork, get your laptop, meet the team, and finally receive access to the codebase.&lt;/p&gt;

&lt;p&gt;You open the repository expecting to get started.&lt;/p&gt;

&lt;p&gt;Then you see it: hundreds of files, folders inside folders, components importing other components, services calling other services, and names that seem familiar but don't tell you much about what the code actually does.&lt;/p&gt;

&lt;p&gt;You know the language. You know the framework. You have built applications before.&lt;/p&gt;

&lt;p&gt;But suddenly, even a small task feels harder than it should.&lt;/p&gt;

&lt;p&gt;This is one of the uncomfortable parts of switching jobs as a software developer: &lt;strong&gt;you are experienced enough to write the code, but you don't yet understand the system you're expected to change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that gap can make the first few weeks feel much longer than they need to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowing the stack isn't the same as knowing the codebase
&lt;/h2&gt;

&lt;p&gt;A new job often comes with the assumption that your technical experience will transfer immediately. In some ways, it does. Your knowledge of JavaScript, React, Node.js, databases, testing, or deployment still matters.&lt;/p&gt;

&lt;p&gt;What doesn't transfer automatically is the context around those technologies.&lt;/p&gt;

&lt;p&gt;Every codebase has its own history and conventions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where the team puts business logic.&lt;/li&gt;
&lt;li&gt;How components communicate with services.&lt;/li&gt;
&lt;li&gt;How API requests are structured.&lt;/li&gt;
&lt;li&gt;Where validation and error handling happen.&lt;/li&gt;
&lt;li&gt;Which abstractions are intentional and which are historical.&lt;/li&gt;
&lt;li&gt;How data moves through the application.&lt;/li&gt;
&lt;li&gt;What needs to be tested when a particular part changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two teams can use the same stack and organize their applications very differently.&lt;/p&gt;

&lt;p&gt;You might be comfortable building a React application from scratch, but that doesn't mean you'll immediately know where a particular team handles authentication, permissions, caching, or form state.&lt;/p&gt;

&lt;p&gt;The challenge isn't that you've forgotten how to code. You're missing the context that makes the code understandable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The temptation to understand everything
&lt;/h2&gt;

&lt;p&gt;When developers feel lost in a repository, a common reaction is to start reading files.&lt;/p&gt;

&lt;p&gt;You open the application entry point. Then a router. Then a layout. A component imports a hook, the hook calls a service, and the service imports an API client. You follow another import and end up somewhere completely different.&lt;/p&gt;

&lt;p&gt;An hour later, you've read a lot of code but still can't confidently explain how one feature works.&lt;/p&gt;

&lt;p&gt;This happens because a repository is not a book that needs to be read from beginning to end. Its file structure is only one clue about the system. Reading files without a question gives you details without necessarily giving you a useful mental model.&lt;/p&gt;

&lt;p&gt;A better starting point is smaller: find one behavior you need to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with one feature you can follow
&lt;/h2&gt;

&lt;p&gt;Imagine you're asked to make a small change to the login experience.&lt;/p&gt;

&lt;p&gt;Instead of exploring every authentication-related file at once, begin with the interaction itself.&lt;/p&gt;

&lt;p&gt;What happens when someone submits the login form?&lt;/p&gt;

&lt;p&gt;In a typical web application, the path might look something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user enters credentials and submits a form.&lt;/li&gt;
&lt;li&gt;A component handles the submit event.&lt;/li&gt;
&lt;li&gt;A function validates or prepares the input.&lt;/li&gt;
&lt;li&gt;A client sends a request to an API endpoint.&lt;/li&gt;
&lt;li&gt;A backend route passes the request to the relevant service.&lt;/li&gt;
&lt;li&gt;The server returns a response.&lt;/li&gt;
&lt;li&gt;The frontend updates the interface based on the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is an illustrative flow, not a claim about every application's architecture. Your project may use different boundaries, naming conventions, or authentication mechanisms.&lt;/p&gt;

&lt;p&gt;The point is to follow one complete path from the action a user takes to the result they see.&lt;/p&gt;

&lt;p&gt;As you trace it, note the files that actually participate in the behavior. You may discover that a feature is spread across a page, a custom hook, an API client, a backend route, and a service. You now have a concrete starting map instead of a vague impression of the entire repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the places where execution begins
&lt;/h2&gt;

&lt;p&gt;Once you have a behavior in mind, look for the places where the application receives work.&lt;/p&gt;

&lt;p&gt;In a frontend application, that might mean locating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application entry file.&lt;/li&gt;
&lt;li&gt;The router or route definitions.&lt;/li&gt;
&lt;li&gt;The layout surrounding the relevant page.&lt;/li&gt;
&lt;li&gt;The page or component that owns the interaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a backend application, relevant starting points might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server startup file.&lt;/li&gt;
&lt;li&gt;HTTP route definitions.&lt;/li&gt;
&lt;li&gt;Middleware.&lt;/li&gt;
&lt;li&gt;Queue consumers or background jobs.&lt;/li&gt;
&lt;li&gt;Scheduled tasks or event handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are examples, not a universal folder structure. A monolith, a monorepo, a serverless application, and a distributed system can have very different entry points.&lt;/p&gt;

&lt;p&gt;The useful question is not “What is the most important file in this repository?” It is “Where does the behavior I'm investigating enter this part of the system?”&lt;/p&gt;

&lt;p&gt;That question keeps exploration tied to the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the running application to check your assumptions
&lt;/h2&gt;

&lt;p&gt;Reading code gives you a theory of what should happen. Running the application helps you see what actually happens.&lt;/p&gt;

&lt;p&gt;If you can reproduce the behavior locally or in an approved development environment, use the tools available to inspect it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put a breakpoint where the interaction begins.&lt;/li&gt;
&lt;li&gt;Step through the relevant function calls.&lt;/li&gt;
&lt;li&gt;Inspect the values passed between layers.&lt;/li&gt;
&lt;li&gt;Check the network request and response.&lt;/li&gt;
&lt;li&gt;Add a temporary, targeted log when the existing observability is insufficient.&lt;/li&gt;
&lt;li&gt;Run the relevant tests to understand expected behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if a form behaves unexpectedly, inspect the value at the event handler, then at the API boundary, rather than guessing which component is responsible.&lt;/p&gt;

&lt;p&gt;Be careful with logs: they can expose tokens, personal data, or other sensitive values. Avoid logging secrets and remove temporary debugging statements before committing changes.&lt;/p&gt;

&lt;p&gt;Tests are useful evidence too, but they are not automatically a complete description of the system. A test may cover only one case, or it may reflect behavior that has since changed. Read what it asserts and consider whether it covers the path you're investigating.&lt;/p&gt;

&lt;p&gt;The goal is to replace assumptions with observations wherever you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn the team's patterns before introducing your own
&lt;/h2&gt;

&lt;p&gt;At some point, you'll need to change something. Before creating a new abstraction or writing a new implementation, look for a similar feature that already works.&lt;/p&gt;

&lt;p&gt;If you're adding an API endpoint, inspect another endpoint with comparable responsibilities.&lt;/p&gt;

&lt;p&gt;If you're changing a React component, find one that handles a similar interaction.&lt;/p&gt;

&lt;p&gt;If you're adding validation, look at how the project handles validation and errors elsewhere.&lt;/p&gt;

&lt;p&gt;Pay attention to more than naming. Look at where logic lives, how dependencies are passed, how loading and error states are represented, how tests are organized, and what conventions the team follows.&lt;/p&gt;

&lt;p&gt;Existing code is not automatically good code, and copying a pattern without understanding its context can carry forward a mistake. Treat it as evidence of how the project currently works—not as proof that every implementation decision is ideal.&lt;/p&gt;

&lt;p&gt;When a pattern seems inconsistent, ask a teammate before assuming it is safe to standardize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a small map as you explore
&lt;/h2&gt;

&lt;p&gt;You don't need a complete architecture document to become productive. A short set of notes is often enough to stop repeating the same investigations.&lt;/p&gt;

&lt;p&gt;For the feature you're working on, record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The route, page, or entry point.&lt;/li&gt;
&lt;li&gt;The main components or handlers involved.&lt;/li&gt;
&lt;li&gt;The service or API boundary.&lt;/li&gt;
&lt;li&gt;The backend route or job, if relevant.&lt;/li&gt;
&lt;li&gt;The tests that cover the behavior.&lt;/li&gt;
&lt;li&gt;Any important dependencies or unresolved questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple flow written in plain language is useful:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Login form → submit handler → auth client → API route → authentication service → response → UI state&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Adjust it to match what you actually found. Don't fill in unknown parts just to make the diagram look complete.&lt;/p&gt;

&lt;p&gt;These notes become especially useful when you return to the feature a few days later, need to explain your change in a review, or discover that another task touches the same area.&lt;/p&gt;

&lt;h2&gt;
  
  
  You don't need to know the whole repository before contributing
&lt;/h2&gt;

&lt;p&gt;There is a point where more exploration stops helping.&lt;/p&gt;

&lt;p&gt;You may be ready to make a small change when you can explain the relevant behavior, identify the likely files involved, understand the project's existing pattern, and name the checks that should give you confidence in the change.&lt;/p&gt;

&lt;p&gt;That does not mean you understand every dependency or every architectural decision. It means you understand enough of the part you're touching to make a deliberate change—and you know what you still need to verify.&lt;/p&gt;

&lt;p&gt;Start with a small, reviewable contribution. Run the relevant checks. Ask focused questions when you reach a boundary you cannot confidently cross. Expand your map as the work takes you into other parts of the system.&lt;/p&gt;

&lt;p&gt;The first few weeks in a new engineering role can feel slow because you're learning a product's history and a team's way of working at the same time as you're learning the code.&lt;/p&gt;

&lt;p&gt;That's normal. You don't have to turn the entire repository into a mental model on day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You just need to understand the next piece of the system well enough to work on it responsibly.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>softwareengineering</category>
      <category>career</category>
    </item>
    <item>
      <title>Choosing Local AI Hardware by Workload, Not Hype</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Wed, 28 Oct 2026 17:59:16 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/choosing-local-ai-hardware-by-workload-not-hype-4nkj</link>
      <guid>https://dev.to/mdazlaanzubair/choosing-local-ai-hardware-by-workload-not-hype-4nkj</guid>
      <description>&lt;p&gt;Local AI buying advice often starts with a GPU shortlist. A better starting point is the workload: what do you want to run, how much memory does it need, and how much latency or setup work can you tolerate?&lt;/p&gt;

&lt;p&gt;The value-first answer is often less exciting than a flagship build: &lt;strong&gt;use the computer you already own, test a compact quantized model, and upgrade only after you can name the bottleneck.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with memory
&lt;/h2&gt;

&lt;p&gt;For local language models, GPU VRAM is often the constraint that decides which models fit comfortably. Model weights are only part of the footprint: the runtime, context cache, image inputs and other applications also use memory. Quantization can reduce weight memory, but it does not remove all overhead and can affect output quality.&lt;/p&gt;

&lt;p&gt;That is why shopping by parameter count or peak compute alone can mislead. Check the exact model variant, quantization, context length, runtime and operating-system support before spending. Hardware-fit tools provide estimates, not guarantees; compare them with model cards and your own workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four value-first starting points
&lt;/h2&gt;

&lt;h3&gt;
  
  
  General use: chat, summaries and writing
&lt;/h3&gt;

&lt;p&gt;Start with your current computer and try a compact quantized model such as &lt;strong&gt;Qwen3 8B&lt;/strong&gt;. If you have enough memory and need image understanding, evaluate &lt;strong&gt;Gemma 4 12B&lt;/strong&gt;. A smaller model can be easier to fit and iterate on, but may be less reliable on complex reasoning or long documents. Local inference also does not automatically provide current web knowledge or hosted-service convenience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Engineering and development
&lt;/h3&gt;

&lt;p&gt;A desktop GPU with &lt;strong&gt;16 GB VRAM&lt;/strong&gt; is a useful middle ground for coding assistants, repository Q&amp;amp;A, test generation and experimentation. Consider &lt;strong&gt;24 GB&lt;/strong&gt; if larger quantized models or longer contexts matter. Compare a current Qwen coding/instruct variant with Gemma 4 12B, and test patch quality, repository-level reasoning and tool calls against your own codebase. Keep a hosted model available for tasks where local quality falls short.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design and video
&lt;/h3&gt;

&lt;p&gt;Choose the actual image or video pipeline before buying hardware. &lt;strong&gt;16–24 GB VRAM&lt;/strong&gt; is a starting range to investigate for image workflows; heavier video-generation work can need more capacity. A multimodal LLM such as Gemma 4 can help understand images when the chosen variant supports image input, but it does not replace a dedicated image- or video-generation model. Check the requirements of the exact app, model and runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation and assistants
&lt;/h3&gt;

&lt;p&gt;Separate the always-on controller from inference. An existing mini PC or low-power desktop can host schedules, integrations, a workflow engine, logs, a database and persistent state. Evaluate Qwen3 8B/14B or Gemma 4 12B for bounded tasks, but test structured output, tool selection and recovery—not just fluent chat. Permissions, retries, observability and human approval are part of the system design.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical pre-purchase checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Define the real workload: chat, coding, image generation, video generation or agents.&lt;/li&gt;
&lt;li&gt;Check VRAM or unified memory for the exact quantization and context.&lt;/li&gt;
&lt;li&gt;Include system RAM, SSD capacity, power, cooling, noise and electricity in total cost.&lt;/li&gt;
&lt;li&gt;Verify the model license, runtime support and integrations.&lt;/li&gt;
&lt;li&gt;Compare local and hosted options using your own usage pattern.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a decision guide, not a lab benchmark. Prices and model releases change quickly; treat third-party price examples as snapshots and verify current local availability. The best-value setup is the least expensive reliable system that meets your quality, latency, privacy and workflow needs—with enough headroom to avoid replacing it immediately.&lt;/p&gt;

&lt;p&gt;Useful starting points include &lt;a href="https://llmconfigurator.com/en/build" rel="noopener noreferrer"&gt;LLM Configurator&lt;/a&gt;, &lt;a href="https://huggingface.co/models" rel="noopener noreferrer"&gt;Hugging Face Models&lt;/a&gt;, &lt;a href="https://artificialanalysis.ai/models/open-source" rel="noopener noreferrer"&gt;Artificial Analysis open models&lt;/a&gt; and the &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;Ollama model library&lt;/a&gt;. Check exact model cards and licenses before adoption.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://letinix.com/articles/compare/best-value-local-ai-hardware-models" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>devto</category>
      <category>hardware</category>
    </item>
    <item>
      <title>Cron Syntax Explained: Fields, Operators, and Common Schedules</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:07:31 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/cron-syntax-explained-fields-operators-and-common-schedules-14mg</link>
      <guid>https://dev.to/mdazlaanzubair/cron-syntax-explained-fields-operators-and-common-schedules-14mg</guid>
      <description>&lt;p&gt;A standard five-field cron expression describes &lt;strong&gt;when a scheduler should trigger a task&lt;/strong&gt;: minute, hour, day of month, month, and day of week. For example, &lt;code&gt;*/5 * * * *&lt;/code&gt; matches every five-minute mark, while &lt;code&gt;0 9 * * 1-5&lt;/code&gt; matches 09:00 Monday through Friday under the traditional Unix cron interpretation.&lt;/p&gt;

&lt;p&gt;Those expressions are not universally portable. Cron implementations differ in supported fields, weekday numbering, timezone configuration, and how they interpret edge cases. Identify the scheduler first, then validate the expression against that scheduler's documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five fields in a cron expression
&lt;/h2&gt;

&lt;p&gt;In traditional Unix &lt;code&gt;crontab&lt;/code&gt;, the five time fields appear in this order:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F080x5s4m0gxl6sq3mqzq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F080x5s4m0gxl6sq3mqzq.webp" alt="Five-field cron expression layout showing minute, hour, day of month, month, and day of week." width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The five time fields in a traditional Unix cron expression&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Common range&lt;/th&gt;
&lt;th&gt;Example meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minute&lt;/td&gt;
&lt;td&gt;0–59&lt;/td&gt;
&lt;td&gt;15 means at minute 15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hour&lt;/td&gt;
&lt;td&gt;0–23&lt;/td&gt;
&lt;td&gt;9 means 9 AM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day of month&lt;/td&gt;
&lt;td&gt;1–31&lt;/td&gt;
&lt;td&gt;1 means the first calendar day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month&lt;/td&gt;
&lt;td&gt;1–12&lt;/td&gt;
&lt;td&gt;6 means June&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day of week&lt;/td&gt;
&lt;td&gt;0–7 in Linux cron&lt;/td&gt;
&lt;td&gt;1 means Monday; 0 or 7 means Sunday&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The command or workflow configuration comes after the time fields in a crontab entry. A cron expression copied into a framework configuration may be parsed differently, so do not assume every field range or extension is identical. The &lt;a href="https://man7.org/linux/man-pages/man5/crontab.5.html" rel="noopener noreferrer"&gt;Linux crontab(5) manual&lt;/a&gt; documents the traditional five-field layout and Linux cron's day-of-week convention.&lt;/p&gt;
&lt;h2&gt;
  
  
  The main cron operators
&lt;/h2&gt;

&lt;p&gt;Common five-field cron formats use these operators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;* — every allowed value in that field.&lt;/li&gt;
&lt;li&gt;, — a list of specific values, such as 1,15.&lt;/li&gt;
&lt;li&gt;- — an inclusive range, such as 1-5.&lt;/li&gt;
&lt;li&gt;/ — a step within a field, such as */5 for every fifth minute value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples below use the traditional five-field Unix cron format. Their descriptions are expected interpretations of the expressions, not observations from a running scheduler.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;Expected interpretation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;* * * * *&lt;/td&gt;
&lt;td&gt;Every minute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*/5 * * * *&lt;/td&gt;
&lt;td&gt;Every five minutes, at minute values 0, 5, 10, and so on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0 * * * *&lt;/td&gt;
&lt;td&gt;At the start of every hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0 9 * * 1-5&lt;/td&gt;
&lt;td&gt;At 09:00 Monday through Friday&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0 0 1 * *&lt;/td&gt;
&lt;td&gt;At midnight on the first day of each month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30 8 * * 0&lt;/td&gt;
&lt;td&gt;At 08:30 every Sunday in Linux cron, where 0 means Sunday&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A step is evaluated within its field's range. For example, &lt;code&gt;*/5&lt;/code&gt; in the minute field means the minute values divisible by five. It does not mean “wait five minutes after this job finishes,” and it does not create a durable interval measured from the time the job was installed.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to read an expression from left to right
&lt;/h2&gt;

&lt;p&gt;Take this expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15 6 * * 1-5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read each field in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;15 — minute 15.&lt;/li&gt;
&lt;li&gt;6 — hour 6, using a 24-hour clock.&lt;/li&gt;
&lt;li&gt;* — every day of the month.&lt;/li&gt;
&lt;li&gt;* — every month.&lt;/li&gt;
&lt;li&gt;1-5 — Monday through Friday in the traditional Linux cron convention.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The expected interpretation is 06:15 on weekdays, in the timezone used by the scheduler. The expression itself does not contain a timezone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The day-of-month and day-of-week rule
&lt;/h2&gt;

&lt;p&gt;One of the easiest mistakes is restricting both the day-of-month and day-of-week fields and assuming they form an AND condition.&lt;/p&gt;

&lt;p&gt;In the traditional Linux cron behavior documented by &lt;code&gt;crontab(5)&lt;/code&gt;, when &lt;strong&gt;both fields are restricted&lt;/strong&gt; (neither is *), a job runs when either field matches. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 9 1 * 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is expected to match 09:00 on the first day of each month and 09:00 on Mondays, not only Mondays that fall on the first. This rule is implementation-specific; check the target scheduler before transferring the expression elsewhere.&lt;/p&gt;

&lt;p&gt;If you intend “the first day of the month, only when it is Monday,” traditional cron's five fields do not express that AND condition directly. Use a scheduler with suitable calendar rules or make the additional condition explicit in the job itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weekday numbering is not universal
&lt;/h2&gt;

&lt;p&gt;Do not copy weekday numbers between schedulers without checking the target's convention. The Linux &lt;code&gt;crontab(5)&lt;/code&gt; manual accepts &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;7&lt;/code&gt; for Sunday and &lt;code&gt;1–6&lt;/code&gt; for Monday through Saturday. GitHub Actions documents its own five-field schedule syntax with weekday values &lt;code&gt;0–6&lt;/code&gt;, where Sunday is &lt;code&gt;0&lt;/code&gt;. &lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax" rel="noopener noreferrer"&gt;Workflow syntax for GitHub Actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Names such as MON or JAN, a seconds field, and special tokens such as ? or L are not part of the portable five-field baseline. Some schedulers support extensions; others reject them or interpret them differently. Use the scheduler's primary documentation as the authority for its accepted syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time zones and daylight-saving time
&lt;/h2&gt;

&lt;p&gt;A cron expression specifies calendar fields, not a timezone. The effective timezone comes from the scheduler or its configuration. A schedule intended for 09:00 local time may therefore run at a different local hour if the scheduler evaluates it in UTC or another zone.&lt;/p&gt;

&lt;p&gt;Daylight-saving transitions are also scheduler-specific. The Linux &lt;code&gt;crontab(5)&lt;/code&gt; manual notes that nonexistent local times during a spring-forward transition do not match, while repeated times during a fall-back transition can run twice. Other platforms may use different rules. If a task must run once per business day, avoid assuming that the same expression guarantees identical behavior across every DST transition.&lt;/p&gt;

&lt;p&gt;For a production schedule, confirm all three items:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which timezone the scheduler actually uses.&lt;/li&gt;
&lt;li&gt;How that scheduler handles skipped or repeated local times.&lt;/li&gt;
&lt;li&gt;Whether a delayed, skipped, or duplicate trigger is acceptable for the task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A scheduled trigger is not a guarantee that the work will start exactly on time or finish successfully. The scheduler, host, queue, and job implementation all affect execution and recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and check an expression
&lt;/h2&gt;

&lt;p&gt;Start with the intended schedule in plain language—for example, “every weekday at 09:00 in the scheduler's configured timezone.” Translate that requirement into the target scheduler's dialect, then check the expression and its expected calendar matches before deploying it.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://letinix.com/tools/cron-expression-builder" rel="noopener noreferrer"&gt;Letinix Cron Expression Builder&lt;/a&gt; is the relevant utility when you want to construct or inspect an expression directly. Check its current format and preview assumptions against the scheduler you are configuring; a builder does not replace the scheduler's own validation or documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short validation checklist
&lt;/h2&gt;

&lt;p&gt;Before saving a cron schedule, verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The target expects five fields rather than a six-field format with seconds.&lt;/li&gt;
&lt;li&gt;Each field uses the target's accepted range and operators.&lt;/li&gt;
&lt;li&gt;Weekday numbering matches the target scheduler.&lt;/li&gt;
&lt;li&gt;Restricted day-of-month and day-of-week fields have the intended combined behavior.&lt;/li&gt;
&lt;li&gt;The scheduler's timezone and daylight-saving behavior match the requirement.&lt;/li&gt;
&lt;li&gt;The job is safe if it starts late, is skipped, runs twice, overlaps a previous run, or fails after being triggered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Linux-specific behavior, use the &lt;a href="https://man7.org/linux/man-pages/man5/crontab.5.html" rel="noopener noreferrer"&gt;Linux crontab(5) manual&lt;/a&gt;. For GitHub Actions, use the official &lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax" rel="noopener noreferrer"&gt;workflow syntax reference&lt;/a&gt; and &lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows" rel="noopener noreferrer"&gt;events that trigger workflows&lt;/a&gt;. Other platforms should be checked against their own scheduler documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://man7.org/linux/man-pages/man5/crontab.5.html" rel="noopener noreferrer"&gt;crontab(5) — Linux manual page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax" rel="noopener noreferrer"&gt;Workflow syntax for GitHub Actions — GitHub Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows" rel="noopener noreferrer"&gt;Events that trigger workflows — GitHub Docs&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/cron-syntax-explained" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
      <category>automation</category>
    </item>
    <item>
      <title>How to Estimate the Cost of an AI Agent Workflow</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:07:10 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/how-to-estimate-the-cost-of-an-ai-agent-workflow-6pd</link>
      <guid>https://dev.to/mdazlaanzubair/how-to-estimate-the-cost-of-an-ai-agent-workflow-6pd</guid>
      <description>&lt;p&gt;To estimate AI agent API costs, calculate the cost of each model call in the workflow, add separately billed tools and infrastructure, then account for retries and multiply by expected task volume. A single user request can trigger several model calls, and later calls may resend a larger context than the first. Estimating only the initial prompt will usually miss part of the bill.&lt;/p&gt;

&lt;p&gt;A practical estimate starts with a workflow map and a small set of scenarios. For every model call, record input tokens, output tokens, model and pricing tier. Add tool charges where the provider bills them separately. Then calculate a normal path, a high-usage path and the cost of failures or retries.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://letinix.com/tools/llm-api-cost-calculator" rel="noopener noreferrer"&gt;Letinix LLM API Cost Calculator&lt;/a&gt; can calculate token-cost scenarios from prices and token counts you enter. It does not model an entire agent graph automatically, so use it for call classes or totals after you have mapped the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Map one task from start to finish
&lt;/h2&gt;

&lt;p&gt;Start with a specific task, such as answering a support question using a knowledge base, summarizing a set of documents, or researching a topic and producing a report. Draw the sequence of steps that may require model inference or a paid tool.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interpret the task: the model receives the instructions and user request.&lt;/li&gt;
&lt;li&gt;Choose an action: the model decides whether to call a tool or continue reasoning.&lt;/li&gt;
&lt;li&gt;Run the tool: your application executes a search, database lookup, code operation or external API call.&lt;/li&gt;
&lt;li&gt;Read the result: the tool output is sent back to the model, which may choose another action.&lt;/li&gt;
&lt;li&gt;Produce the answer: the model generates a final response or structured result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is an illustrative pattern, not a required architecture. A simple agent may use one model call and one tool; a longer-running agent may loop through multiple tools and model calls. Measure the workflow your application actually uses rather than assuming every task follows the same path.&lt;/p&gt;

&lt;p&gt;For each model call, record the model and pricing tier; input tokens including instructions, conversation state, tool definitions, retrieved documents and previous tool results that are sent again; output tokens including reasoning tokens when billed; cache assumptions; and any separate tool or service fee.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Calculate each model call separately
&lt;/h2&gt;

&lt;p&gt;For a simple text call without caching, use the provider’s current input and output rates per million tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call input cost  = input tokens  / 1,000,000 × input rate
call output cost = output tokens / 1,000,000 × output rate
call cost        = call input cost + call output cost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat this for every call in the workflow, then add the results. Do not count one user action as one model request unless the implementation really makes only one call.&lt;/p&gt;

&lt;p&gt;For example, an agent may first receive a short request, then send the model a tool schema, then send a large search result, then make a final call with accumulated context. Those calls can have different token counts. If a call resends prior conversation or tool output, those tokens can be billed again as input unless the provider’s caching rules apply.&lt;/p&gt;

&lt;p&gt;The official documentation explains provider-specific billing details: &lt;a href="https://developers.openai.com/api/docs/pricing" rel="noopener noreferrer"&gt;OpenAI API pricing&lt;/a&gt;&lt;a href="https://platform.claude.com/docs/en/about-claude/pricing" rel="noopener noreferrer"&gt;Anthropic Claude pricing&lt;/a&gt;&lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API pricing&lt;/a&gt;. Anthropic documents tool definitions and results as part of tool-use tokens, Google documents intermediate input and reasoning tokens in agentic loops, and OpenAI lists separate fees for some tools. Check the current page for the selected model and feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Build a per-task estimate
&lt;/h2&gt;

&lt;p&gt;Consider this hypothetical workflow with four model calls. These are illustrative inputs, not measurements from a deployed agent. Assume an input rate of $2 per million tokens and an output rate of $8 per million tokens solely to show the arithmetic.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model call&lt;/th&gt;
&lt;th&gt;Input tokens&lt;/th&gt;
&lt;th&gt;Output tokens&lt;/th&gt;
&lt;th&gt;Estimated token cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Interpret request&lt;/td&gt;
&lt;td&gt;1,200&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;$0.0048&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choose tool/action&lt;/td&gt;
&lt;td&gt;2,500&lt;/td&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;$0.0082&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Process tool result&lt;/td&gt;
&lt;td&gt;4,200&lt;/td&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;$0.0132&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate final answer&lt;/td&gt;
&lt;td&gt;5,000&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;$0.0172&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;12,900&lt;/td&gt;
&lt;td&gt;2,200&lt;/td&gt;
&lt;td&gt;$0.0434&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The example uses the same hypothetical rates for each call. The cost for each row is calculated from that row’s input and output tokens; the total is the sum of the four rows. The growing input count illustrates one source of cost: later calls may include tool output and more task context.&lt;/p&gt;

&lt;p&gt;Now assume the workflow also incurs a hypothetical $0.01 in separate tool charges per completed task. The estimated total becomes $0.0534 per task before retries, infrastructure, logging, storage or other omitted costs. The $0.01 is an illustrative assumption, not a quoted provider fee.&lt;/p&gt;

&lt;p&gt;For a real workflow, replace these values with API-reported token usage and current prices. If different calls use different models, use the corresponding rates for each call rather than applying one blended rate to the entire workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fch7z55x6e1j4uojlrtkc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fch7z55x6e1j4uojlrtkc.webp" alt="A workflow cost map separates model calls, tool charges, and retry overhead before scaling to monthly task volume." width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Conceptual estimation model; actual workflow steps and charges vary by implementation.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Add tool fees and other billable operations
&lt;/h2&gt;

&lt;p&gt;A tool call is not always billed as a single flat fee. Depending on the provider and tool, the cost may include model tokens associated with tool use; a separate fee for a server-side search or hosted execution feature; an external service’s fee; and application infrastructure such as compute, queueing, database reads, storage, observability and network services.&lt;/p&gt;

&lt;p&gt;Avoid double-counting. If a provider’s usage report already includes tool-related tokens in model input/output, do not add those tokens a second time. Add a separate fee only when the relevant pricing or invoice identifies one. The provider docs govern provider charges; other vendors’ billing terms govern external services.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Model retries and incomplete tasks
&lt;/h2&gt;

&lt;p&gt;Retries matter because a failed or incomplete attempt may already have incurred model or tool costs. Examples include a tool timeout after the model has generated a call, an invalid tool result that triggers another model request, or a final answer that fails validation and must be regenerated. Whether a particular failure is billable depends on the API and when the failure occurs; do not assume all failed requests are free or all are charged identically.&lt;/p&gt;

&lt;p&gt;For a first estimate, use observed retry rates if you have traces. If you do not, state an explicit assumption and keep it separate from the base workflow cost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expected cost per task = base cost × (1 + retry rate)
                       = $0.0534 × 1.08
                       = $0.057672
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplified scenario assumes one additional full-cost attempt for 8% of tasks, with no further retries. Actual retries may cost less or more than the original path. If failures trigger only one small model call, estimate that retry path separately instead of multiplying the whole workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Scale the estimate to monthly volume
&lt;/h2&gt;

&lt;p&gt;Once you have a per-task estimate, multiply it by expected completed tasks per month. Keep task volume distinct from model-call volume: one task may contain multiple calls, and some tasks may fail or be retried.&lt;/p&gt;

&lt;p&gt;Using the hypothetical $0.057672 expected cost above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,000 tasks per month: $57.67&lt;/li&gt;
&lt;li&gt;10,000 tasks per month: $576.72&lt;/li&gt;
&lt;li&gt;100,000 tasks per month: $5,767.20&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These figures include the illustrative tool fee and simplified retry assumption, but exclude infrastructure and any other charges not listed. They are not a forecast for a particular provider or product.&lt;/p&gt;

&lt;p&gt;Create at least three scenarios: low usage with shorter contexts and fewer tool calls; expected usage based on measured token counts and observed retry rates; and a high but plausible case with long retrieved results, additional loops or longer outputs. Recalculate when prompts, tools, retrieval limits, model routing or user behavior change.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. A small estimator for call-level token usage
&lt;/h2&gt;

&lt;p&gt;If you have a trace or spreadsheet of model calls, this Python example shows how to total token costs and add explicit per-task tool fees. It is a starting point for adapting your own usage export, not a tested integration with a provider API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;estimate_agent_cost.py&lt;/strong&gt;&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_task_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_fees&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Estimate one workflow run from per-call token counts and explicit fees.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;input_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;input_rate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;
    &lt;span class="n"&gt;output_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;output_rate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;output_cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_fees&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tool_fees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;output_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tool_fees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Hypothetical example; replace with token usage from your own traces.
&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;estimate_task_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;tool_fees&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output for these hypothetical inputs is an estimated total of $0.0534, with 12,900 input tokens and 2,200 output tokens. The code does not fetch prices, infer retries, apply caching, or identify external infrastructure charges. Feed it actual usage for each model call, use the rate for that call’s model, and extend the model if calls use different rates or cached-input categories.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Use the calculator for the parts it supports
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://letinix.com/tools/llm-api-cost-calculator" rel="noopener noreferrer"&gt;Letinix LLM API Cost Calculator&lt;/a&gt; accepts input and output prices per million tokens, token counts per request, request volume and optional cached-input assumptions. It returns per-request, daily, monthly and yearly estimates.&lt;/p&gt;

&lt;p&gt;For an agent workflow, enter representative token totals and a blended rate only if all included calls share that rate and billing category. Otherwise, calculate separate call classes when steps use different models, rates, cache behavior or tool fees, then add the results in a separate worksheet.&lt;/p&gt;

&lt;p&gt;The calculator does not automatically model branching workflows, per-step model routing, retries, separate tool charges, every modality or application infrastructure. Its output is a scenario estimate, not an invoice. For more detail, see &lt;a href="https://letinix.com/articles/build/llm-input-output-token-pricing" rel="noopener noreferrer"&gt;LLM input vs. output token pricing&lt;/a&gt;&lt;a href="https://letinix.com/articles/build/how-to-estimate-llm-api-costs" rel="noopener noreferrer"&gt;how to estimate LLM API costs before launch&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.openai.com/api/docs/pricing" rel="noopener noreferrer"&gt;Pricing — OpenAI API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.openai.com/api/docs/guides/tools-web-search" rel="noopener noreferrer"&gt;Web search — OpenAI API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://platform.claude.com/docs/en/about-claude/pricing" rel="noopener noreferrer"&gt;Pricing — Anthropic Claude Platform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Gemini API pricing — Google AI for Developers&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/estimate-ai-agent-api-costs" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Convert a JSON API Response to TypeScript Types</title>
      <dc:creator>Muhammad Azlaan Zubair</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:06:43 +0000</pubDate>
      <link>https://dev.to/mdazlaanzubair/how-to-convert-a-json-api-response-to-typescript-types-2o37</link>
      <guid>https://dev.to/mdazlaanzubair/how-to-convert-a-json-api-response-to-typescript-types-2o37</guid>
      <description>&lt;p&gt;A JSON API response can be converted into TypeScript declarations by mapping each JSON value to a TypeScript type, then extracting nested objects and array items into reusable declarations. A converter is a useful starting point, but the result describes the sample you supplied—not every response the API may return.&lt;/p&gt;

&lt;p&gt;For a quick conversion, paste a representative payload into the &lt;a href="https://letinix.com/tools/json-to-typescript" rel="noopener noreferrer"&gt;Letinix JSON to TypeScript Converter&lt;/a&gt;. Then review optional fields, null values, and any documented API variants before relying on the generated declarations.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with a representative response
&lt;/h2&gt;

&lt;p&gt;Use a response copied from API documentation or a non-sensitive response captured from your own development environment. The following payload is illustrative:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;response.json&lt;/strong&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;"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;42&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;"Mina Chen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"active"&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;"profile"&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;"website"&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;span class="nl"&gt;"roles"&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;"editor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reviewer"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"projects"&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;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="s2"&gt;"p-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;"Docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"archived"&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="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;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="s2"&gt;"p-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;"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;"API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"archived"&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;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;The sample includes primitives, a nested object, arrays, and a nullable value. Those are the structures a generated declaration should represent. It does not show whether website can be a string, whether projects can be omitted, or whether the API sometimes returns other fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Convert the JSON into TypeScript declarations
&lt;/h2&gt;

&lt;p&gt;The converter's documentation describes output for nested objects, arrays, and mixed-type unions. It also exposes options for interface versus type, adding or removing export, and marking properties readonly. The following TypeScript is an illustrative mapping of the JSON above, not a captured output from a live conversion:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;api-types.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Project&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Project&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;archived&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;Each object has a declaration, while the parent refers to nested declarations by name. The roles field becomes string[]; projects becomes an array of Project objects. JSON numbers map to TypeScript number, booleans to boolean, and strings to string.&lt;/p&gt;

&lt;p&gt;For a small object shape, either an interface or a type alias can describe the object. Interfaces are useful for object contracts that may be extended or declaration-merged. Type aliases are more flexible when the type itself must express a union, tuple, or other composite type. Choose based on the model you need, not on a belief that one syntax is universally safer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Review optional and nullable fields
&lt;/h2&gt;

&lt;p&gt;A generated declaration can only infer what the sample reveals. In the example, website is always present and always null, so the declaration website: null is a literal description of that sample. It does not establish the API's full contract.&lt;/p&gt;

&lt;p&gt;If the API documentation says that website is always present but can contain either a URL or null, model that documented contract as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;profile.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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;If the property may be omitted, represent that separate condition with an optional property:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;profile.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;website&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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;With strictNullChecks, reading an optional property also means accounting for undefined. Do not mark every property optional merely to make an interface permissive. Use API documentation, a schema, or multiple representative responses to decide what can actually be absent.&lt;/p&gt;

&lt;p&gt;Objects in the same array can reveal shape differences. For example, if one project object includes archivedAt and another does not, a converter can infer that the key is optional across those observed array items. That is still evidence about the samples, not a guarantee about all future responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Handle mixed arrays and unknown shapes
&lt;/h2&gt;

&lt;p&gt;JSON arrays can contain values of different types. For a sample such as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mixed-values.json&lt;/strong&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;"values"&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="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="s2"&gt;"pending"&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="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 reasonable inferred element type is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;response.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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;The union expresses the observed element types. It does not describe business rules such as which value combinations are valid, whether a string must match a particular set of statuses, or whether an API response can contain a different object variant.&lt;/p&gt;

&lt;p&gt;An empty array is even less informative: there is no element from which to infer an item type. Treat an inferred unknown[] as a signal to consult the API contract or provide a more representative sample, rather than guessing the intended item shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Check the declaration against the API contract
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compare required fields with the API's documented response schema.&lt;/li&gt;
&lt;li&gt;Check nullable properties separately from properties that may be missing.&lt;/li&gt;
&lt;li&gt;Inspect arrays with multiple items and any documented response variants.&lt;/li&gt;
&lt;li&gt;Review dates, identifiers, enum-like strings, and numeric fields. JSON alone does not establish that a string is a valid date or that a number is an integer.&lt;/li&gt;
&lt;li&gt;Decide how to handle additional fields and API version changes.&lt;/li&gt;
&lt;li&gt;If you can, generate types from a maintained API schema rather than relying only on one captured response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a stable, documented API contract, a schema-based workflow may be a better source of truth. For example, openapi-typescript generates TypeScript types from OpenAPI 3.0 and 3.1 schemas. That workflow starts from an API description rather than inferring a contract from a single payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Remember what TypeScript types do not do
&lt;/h2&gt;

&lt;p&gt;TypeScript declarations help the compiler check how your code uses data. They do not inspect an HTTP response at runtime. A declaration such as const user = payload as User does not validate the payload or transform it into a User.&lt;/p&gt;

&lt;p&gt;If the data is untrusted or can change independently of your application, validate it at the boundary. Libraries such as Zod let you define a schema and parse an input; Ajv can compile validators for JSON Schema or JSON Type Definition. The right choice depends on whether you already have a schema, how you want to express constraints, and what error handling your application needs.&lt;/p&gt;

&lt;p&gt;Use the &lt;a href="https://letinix.com/tools/json-to-typescript" rel="noopener noreferrer"&gt;JSON to TypeScript Converter&lt;/a&gt; when you have a JSON sample and need a fast starting declaration. Treat the output as generated source code to review—not as proof that the API contract is complete or that the data is valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treating one response as the entire contract. Collect multiple samples or use the authoritative schema.&lt;/li&gt;
&lt;li&gt;Confusing null with a missing property. T | null and property?: T model different conditions.&lt;/li&gt;
&lt;li&gt;Assuming a type assertion validates data. It only changes what the compiler assumes.&lt;/li&gt;
&lt;li&gt;Inferring semantics from primitive types. A string does not prove a value is a valid date, URL, or known status.&lt;/li&gt;
&lt;li&gt;Ignoring contract drift. Regenerate or update types when the API contract changes, and validate incoming data where runtime correctness matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://letinix.com/tools/json-to-typescript" rel="noopener noreferrer"&gt;JSON to TypeScript Converter — Letinix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/objects.html" rel="noopener noreferrer"&gt;TypeScript Handbook: Object Types&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html" rel="noopener noreferrer"&gt;TypeScript Handbook: Everyday Types&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://openapi-ts.dev/cli" rel="noopener noreferrer"&gt;OpenAPI TypeScript: CLI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zod.dev/basics" rel="noopener noreferrer"&gt;Zod: Basic usage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ajv.js.org/guide/typescript.html" rel="noopener noreferrer"&gt;Ajv: Using with TypeScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://json-schema.org/specification" rel="noopener noreferrer"&gt;JSON Schema: Specification&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://letinix.com/articles/build/convert-json-api-response-to-typescript" rel="noopener noreferrer"&gt;Letinix&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
  </channel>
</rss>
