<?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: CJ Cummings</title>
    <description>The latest articles on DEV Community by CJ Cummings (@cjcummings).</description>
    <link>https://dev.to/cjcummings</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%2F3848443%2F0a8739e9-245a-4edb-8273-b74d555b17bc.png</url>
      <title>DEV Community: CJ Cummings</title>
      <link>https://dev.to/cjcummings</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cjcummings"/>
    <language>en</language>
    <item>
      <title>How to Control Overhead Cost for AI Products</title>
      <dc:creator>CJ Cummings</dc:creator>
      <pubDate>Tue, 11 Aug 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/cjcummings/how-to-control-overhead-cost-for-ai-products-5f24</link>
      <guid>https://dev.to/cjcummings/how-to-control-overhead-cost-for-ai-products-5f24</guid>
      <description>&lt;p&gt;Every LLM call in your AI product — a chat message, a doc summary, an MCP tool call — has a non-deterministic cost attached to it. Let a customer upload 1,000 documents instead of 3, and you're getting an invoice from Big LLM you didn't budget for.&lt;/p&gt;

&lt;p&gt;The short version of how you get that under control: measure margin per account, per feature, and per vendor — not just cost. Set enforcement limits that guarantee your worst case. Then price so revenue moves with usage instead of trailing behind it.&lt;/p&gt;

&lt;p&gt;Cost-to-deliver is the metric most teams reach for first, and it's a good start. But it's incomplete, because it's missing revenue. Controlling cost alone only ever caps your downside. The number that actually gives you control is &lt;strong&gt;margin-to-deliver&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Margin-to-deliver&lt;/strong&gt; is the share of what you charge for a unit of delivered value that you keep after the vendor cost of producing it — &lt;code&gt;(charged − overhead) / charged&lt;/code&gt; — measured per account, per feature, or per vendor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Optimize margin-to-deliver and you've got two levers to pull: enforcement and pricing. Here's how we think about both, and the order we'd tackle them in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclosure: I build &lt;a href="https://limitr.dev" rel="noopener noreferrer"&gt;Limitr&lt;/a&gt;, which does this. I use it as the worked example below because it's what I know, but the math and the instrumentation approach apply regardless of what you build on.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;As soon as you have usage overhead, usage-based complexity exists in your product, regardless of pricing model and what you present to your customers.&lt;/p&gt;

&lt;p&gt;This post fills the instrumentation gap between token cost-to-deliver and packaging, which should be simplified into customer language and presentation. Packaging itself is not covered here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage Observability
&lt;/h2&gt;

&lt;p&gt;An effective control strategy starts with &lt;a href="https://limitr.dev/analyze" rel="noopener noreferrer"&gt;observation&lt;/a&gt;. That's why we built an &lt;code&gt;observe&lt;/code&gt; mode directly into our usage limits — you can't control what you can't see.&lt;/p&gt;

&lt;p&gt;Vendor dashboards and API key segmentation might get you through the early days, but that approach falls apart the moment you need per-account, per-vendor, per-feature cost and margin analysis. If you don't believe that yet, check back in a few months once your product's grown up a bit.&lt;/p&gt;

&lt;p&gt;The number you're after is margin-to-deliver. Here's an example:&lt;/p&gt;

&lt;h3&gt;
  
  
  Single account, per-feature usage, last 24 hours (2 vendors, 1 pipeline)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet delivered: 35.67MTok&lt;/li&gt;
&lt;li&gt;Google Gemini delivered: 42.5MTok&lt;/li&gt;
&lt;li&gt;Outcomes delivered: 2,493&lt;/li&gt;
&lt;li&gt;Charged: $53.78&lt;/li&gt;
&lt;li&gt;Overhead: $42.45&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An outcome here is one pipeline run. It may or may not mean anything to the customer — it means something to us.&lt;/p&gt;

&lt;p&gt;Cost-to-deliver: &lt;strong&gt;$42.45&lt;/strong&gt;, or &lt;strong&gt;$0.017&lt;/strong&gt; per outcome.&lt;/p&gt;

&lt;p&gt;Revenue-per-outcome: &lt;strong&gt;$0.0216&lt;/strong&gt;, so margin-per-outcome — (charged − overhead) / charged — comes out to &lt;strong&gt;21.1%&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On average, every successful run nets us about 20% margin, for this account.&lt;/p&gt;

&lt;p&gt;Now we have real numbers to work with. How much lower are we willing to let that margin go? How many more runs before it hits zero, or goes negative? Would a usage limit protect the bottom line, and should every plan or contract get one?&lt;/p&gt;

&lt;h3&gt;
  
  
  Attributing raw usage to outcomes
&lt;/h3&gt;

&lt;p&gt;The hard part is typically the mapping. A pipeline run generally isn't just one call — it's several, possibly across multiple vendors, and you need to know which outcome each one belonged to before any of the above means anything.&lt;/p&gt;

&lt;p&gt;In Limitr, an outcome is just another credit, tracked the same way tokens are. Every &lt;code&gt;allow(...)&lt;/code&gt; call can carry metadata, and it's a common pattern to attribute usage within it, rolling usage up per agent, per feature, via region, the customer's team, or even per run margin and spend data using &lt;a href="https://limitr.dev/spec/concepts#spend-cap" rel="noopener noreferrer"&gt;spend caps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can do this because Limitr is a &lt;a href="https://limitr.dev/blog/we-mean-runtime-literally" rel="noopener noreferrer"&gt;local, context-aware engine&lt;/a&gt; that can track state over many enforcement checks. Pricing stays accurate with or without any of it, but the metadata is what lets you slice the analytics afterward. It's what makes a line item like "this pipeline consumed 132MTok of Sonnet" possible.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Put metrics in terms of real actions or outcomes wherever you can. Keep the raw usage data around for vendor-specific analysis (entitlements should always use the most discrete credit), but the margin-to-deliver KPI itself should be vendor-agnostic — documents read, uploads processed, tool calls made, whatever's meaningful to you.&lt;/p&gt;

&lt;p&gt;That way, when you switch models, you're comparing against outcomes you (and your customer) care about, not an arbitrary token count that only means something to the vendor selling it to you.&lt;/p&gt;

&lt;p&gt;Limitr measures real-time margin for every credit and token, and rolls them up (and translates them) automatically — this example is the simplified version.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Usage Enforcement
&lt;/h2&gt;

&lt;p&gt;Once you can see margin-to-deliver per account, feature, and vendor, the first real lever you have to control it is &lt;a href="https://limitr.dev/control" rel="noopener noreferrer"&gt;enforcement&lt;/a&gt; — deciding what a user has access to and how much of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single account on a "pro" plan @ $200/mo (flat or seats)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AI pipeline @ $0.017 avg cost-to-deliver per outcome&lt;/li&gt;
&lt;li&gt;AI data aggregation @ $0.042 avg cost-to-deliver per refinement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;$200/mo covers 11,764 pipeline runs at that cost. This account used 2,493 in 24 hours — a little over 4 days of runway, nowhere near a 30-day target. Left alone, this account pushes margin negative.&lt;/p&gt;

&lt;p&gt;The simplest fix, without touching price: cap usage. One option is to limit the pro plan to 392 pipeline runs a day, and cut off data aggregation entirely. Worst-case margin-to-deliver is now 0% — you'll never lose money on this feature or account again.&lt;/p&gt;

&lt;p&gt;But you may not make any money on it, either.&lt;/p&gt;




&lt;h2&gt;
  
  
  Usage Monetization
&lt;/h2&gt;

&lt;p&gt;At this point, the case for &lt;a href="https://limitr.dev/monetize" rel="noopener noreferrer"&gt;usage-based pricing&lt;/a&gt; should be clearer. You want revenue to scale with overhead, so margin-to-deliver becomes something you set and optimize through revenue, not just something you defend by cutting cost.&lt;/p&gt;

&lt;p&gt;There's more than one way to do this — plenty of other &lt;a href="https://limitr.dev/blog/design-a-flexible-pricing-model-for-ai" rel="noopener noreferrer"&gt;posts&lt;/a&gt; cover pricing strategy on its own. But every approach depends on being able to analyze and enforce usage first, which is the whole point of the last two sections.&lt;/p&gt;

&lt;p&gt;A few of the options, for the example we've been using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Credit model&lt;/strong&gt; — flexible, supports top-ups, but can be confusing for users when the ROI isn't obvious&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-plus-margin&lt;/strong&gt; — clean and accurate, but rigid, invoices that need explaining, hard to upsell, and it tells the customer exactly what your margin is&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome-based&lt;/strong&gt; — a middle ground, packaged in the customer's language, but harder to guarantee a positive margin-to-deliver on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't mutually exclusive, and the right answer usually differs by feature, by vendor, and by contract. Your objective changes too — margin this month, adoption next. That's the actual argument for keeping the choice in a policy instead of in code: you shouldn't have to ship a release to change your mind.&lt;/p&gt;

&lt;p&gt;Here's what that policy might look like for our "pro" plan:&lt;/p&gt;

&lt;h3&gt;
  
  
  Single account "pro" plan Limitr policy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Monthly subscription: $200/mo (override for annual contracts)&lt;/li&gt;
&lt;li&gt;Includes 5 seats, then $29.99/mo per additional seat (hard limit for annual)&lt;/li&gt;
&lt;li&gt;Includes 30MTok Claude Sonnet tokens/day, then $5/MTok over (hard limit override for margin control on annual + usage governor for SLA)&lt;/li&gt;
&lt;li&gt;Includes 40MTok Google Gemini tokens/day, then $4/MTok over (same overrides)&lt;/li&gt;
&lt;li&gt;Includes 500 AI pipeline runs/day, then $0.02/run over (set to observe + unlimited on enterprise + analytics)&lt;/li&gt;
&lt;li&gt;Includes 100 AI data aggregations/day, then $0.05/aggregation over (same)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The subscription and seats are doing a specific job here: they're the predictable floor that covers your fixed cost regardless of how the account behaves. Everything below them is the part that moves.&lt;/p&gt;

&lt;p&gt;On the contract and invoice (anything presented to the customer), keep it to subscription, seats, and outcomes when possible — in the customer's language, framed as wins where you can. Average cost per outcome makes a good line item. Put the full cost breakdown further down if needed, in its own section, for whoever wants to dig in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example account usage, 1 month
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude Sonnet delivered: 1,080MTok — 900MTok included, 180MTok over&lt;/li&gt;
&lt;li&gt;Google Gemini delivered: 1,290MTok — 1,200MTok included, 90MTok over&lt;/li&gt;
&lt;li&gt;Successful AI pipeline runs: 30,000 — 15,000 included, 15,000 over&lt;/li&gt;
&lt;li&gt;Data aggregations: 4,500 — 3,000 included, 1,500 over&lt;/li&gt;
&lt;li&gt;Seats: 5, all included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Worth noting: that's about 1,000 pipeline runs a day, down from the 2,493 we saw in the first 24-hour window. Usage moves. A plan with a visible included amount and a rate past it changes how an account behaves in a way a flat $200 never does — which is exactly why you want to be watching margin-to-deliver continuously, not modeling it once.&lt;/p&gt;

&lt;h4&gt;
  
  
  Invoiced
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line item&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pro Plan subscription&lt;/td&gt;
&lt;td&gt;5 seats included&lt;/td&gt;
&lt;td&gt;$200.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Pipeline Runs&lt;/td&gt;
&lt;td&gt;30,000 runs — avg $0.041/run&lt;/td&gt;
&lt;td&gt;$1,220.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Aggregations&lt;/td&gt;
&lt;td&gt;4,500 aggregations — avg $0.092/aggregation&lt;/td&gt;
&lt;td&gt;$415.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total due&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1,835.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Usage details
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;AI Pipeline Runs — $1,220.00&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;15,000 runs over plan @ $0.02/run&lt;/td&gt;
&lt;td&gt;$300.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet — 132MTok over @ $5/MTok&lt;/td&gt;
&lt;td&gt;$660.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Gemini — 65MTok over @ $4/MTok&lt;/td&gt;
&lt;td&gt;$260.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Data Aggregations — $415.00&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Amount&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,500 aggregations over plan @ $0.05 each&lt;/td&gt;
&lt;td&gt;$75.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet — 48MTok over @ $5/MTok&lt;/td&gt;
&lt;td&gt;$240.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Gemini — 25MTok over @ $4/MTok&lt;/td&gt;
&lt;td&gt;$100.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Overhead for the month came to $699 — 30,000 runs at $0.017 and 4,500 aggregations at $0.042. Against $1,835 charged, that's a margin-to-deliver of &lt;strong&gt;61.9%&lt;/strong&gt;, up from the 21.1% we started with. Nothing got cheaper. Revenue was just allowed to move with the usage driving the cost.&lt;/p&gt;

&lt;p&gt;The included usage gives you a good baseline margin-to-deliver, depending entirely on any base platform fees. The cost vs price per credit changes the margin-to-deliver for every credit beyond included limits. And separating internal/external outcomes vs vendors vs included provides flexibility per account, feature, and vendor to move margin-to-deliver according to your goals.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A credit model could be used with this exact policy to provide even more flexibility for both the provider and consumer. Included, committed, and/or top-ups of abstract credits can be applied at different exchange rates across all other discrete credits, like tokens.&lt;/p&gt;

&lt;p&gt;For your user, this actually simplifies what they're looking at, because it's one common unit, clearly scaled to make it easier for them to track, budget, allocate, and commit on. Could also allow them to place their own usage caps in a single unit, so that they never go over what they expect, regardless of how they're used.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Two levers, one usage policy
&lt;/h2&gt;

&lt;p&gt;Cost-to-deliver tells you what an account costs. Margin-to-deliver tells you whether it's worth having, and gives you the numbers you need to actually stay in control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enforcement sets your baseline.&lt;/strong&gt; A limit is a guardrail around the worst case. Cap pipeline runs at 392/day and you've decided, in advance, that this account cannot lose you money. It holds whether anyone's watching or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing moves that baseline.&lt;/strong&gt; Charge for overage and revenue rises with cost instead of being eaten by it. That's the 21.1% → 61.9% swing above.&lt;/p&gt;

&lt;p&gt;Enforcement without pricing protects your margin by refusing actions — a 0% floor and a hard cap, for example. For some situations, like agent tool calls or the time an agent gets to converge on a turn, this layer of control makes sense regardless of pricing.&lt;/p&gt;

&lt;p&gt;Pricing without enforcement can scale revenue with cost, right up until one run consumes 300x more AI overhead than accounted for.&lt;/p&gt;

&lt;p&gt;Both require per-account, per-feature, and per-vendor observability. You can't set a limit you can't measure against, and you can't price an outcome you can't count.&lt;/p&gt;

&lt;p&gt;Which is where this usually falls apart. Analytics sit with one vendor, limits sit in application code, prices sit in the billing system — and the three drift. The number you analyzed isn't the number you enforced on, and neither one is the number you invoiced.&lt;/p&gt;

&lt;p&gt;This is what we built the Limitr policy for. One document defines the credits, what they cost you, what you charge for them, what each plan includes, and what happens at the limit — observe, soft, or hard.&lt;/p&gt;

&lt;p&gt;That same document is what executes at the moment of the call. So the margin you're analyzing, the limit you're enforcing, and the line item you're invoicing all come out of one place, in real time, and they can't drift apart.&lt;/p&gt;

&lt;p&gt;To see it in action, check out the &lt;a href="https://limitr.dev/spec/monetize/demo" rel="noopener noreferrer"&gt;live monetization demo&lt;/a&gt; — you can play with a simple policy and track actual usage right in your browser.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webmonetization</category>
      <category>saas</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Actually Cap AI Spend for Your Users: 3 Edge Cases Everyone Misses</title>
      <dc:creator>CJ Cummings</dc:creator>
      <pubDate>Wed, 01 Jul 2026 20:30:16 +0000</pubDate>
      <link>https://dev.to/cjcummings/how-to-actually-cap-ai-spend-for-your-users-3-edge-cases-everyone-misses-2d42</link>
      <guid>https://dev.to/cjcummings/how-to-actually-cap-ai-spend-for-your-users-3-edge-cases-everyone-misses-2d42</guid>
      <description>&lt;p&gt;The spend cap for my first AI project was just a limit on an Anthropic API key.&lt;/p&gt;

&lt;p&gt;Crossing your fingers that users don't find your limit, and that it's high enough for their usage anyway, is a sign that you need a real control layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI spend control is not trivial
&lt;/h2&gt;

&lt;p&gt;It seems like it would be easy, right? It's just a meter per user and a few if statements.&lt;/p&gt;

&lt;p&gt;Then the questions and edge cases start. And don't really stop.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is that meter counting a credit balance burning down, or raw spend counting up?&lt;/li&gt;
&lt;li&gt;Does it include usage the customer's plan already pays for, or only the part that spills over?&lt;/li&gt;
&lt;li&gt;If they've got a promo credit grant active, does &lt;em&gt;that&lt;/em&gt; count against the cap too, or is the cap only for money actually billed?&lt;/li&gt;
&lt;li&gt;Is the meter in my own abstract units or tokens, and how do I map that to all of my vendor costs?&lt;/li&gt;
&lt;li&gt;Does the cap reset on its own schedule, or does it follow the plan, billing period, or token reset schedule?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are exotic. They're among the first questions any real customer conversation raises, and they apply anywhere AI usage gets billed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Limitr Open-Source Project
&lt;/h2&gt;

&lt;p&gt;Defining spend well enough to cap it touches your pricing (vendors, tiers, entitlements), your credit system, and your billing period logic all at once.&lt;/p&gt;

&lt;p&gt;That's why we added spend caps to the Limitr open-source &lt;a href="https://github.com/dev-formata-io/limitr" rel="noopener noreferrer"&gt;project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Limitr is a runtime for observing, enforcing, pricing, and optimizing usage-based software. It enables us to define plans, entitlements, usage limits, and credits as a single config document; managed in one place, enforced everywhere.&lt;/p&gt;

&lt;p&gt;Using it to define, observe, and control costs will make your life much better, for free.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://limitr.dev/" rel="noopener noreferrer"&gt;Limitr Cloud&lt;/a&gt;&lt;/strong&gt; adds managed policies, real-time alerting, billing/payments integrations, analytics, and more on top of the same engine.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Edge 1: Overage-only vs. total spend
&lt;/h2&gt;

&lt;p&gt;Say a customer's plan includes $50/month of AI usage before overage kicks in. You (or they) want to cap their &lt;em&gt;overage&lt;/em&gt; at $20, not their total spend at $20, which would mean they can barely use the feature they're already paying for.&lt;/p&gt;

&lt;p&gt;These are two different caps, and conflating them is a common DIY mistake. A cap that watches total spend will trip long before a cap that watches overage, and customers on a plan with generous included usage will hit a wall that makes no sense to them.&lt;/p&gt;

&lt;p&gt;In Limitr, this is a flag on the cap itself:&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;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCustomerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cap_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_overage_cap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overage_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// only counts spend beyond what the plan includes&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;overage_only&lt;/code&gt;, the cap counts from dollar one. With it, the first $50 of included usage doesn't touch the cap at all — only the spend that spills past the plan boundary does.&lt;/p&gt;




&lt;h2&gt;
  
  
  Edge 2: Does a credit grant count against the cap?
&lt;/h2&gt;

&lt;p&gt;Say you gave this customer a $10 promo credit as a goodwill gesture after a support ticket. They start using it. Does that spend count against their $20 overage cap?&lt;/p&gt;

&lt;p&gt;There's a real argument for both answers. If the cap exists to protect &lt;em&gt;your&lt;/em&gt; margin, promo credit spend absolutely should count — you're still paying the model provider. If the cap exists to protect the &lt;em&gt;customer&lt;/em&gt; from bill shock, credit-covered spend shouldn't count, because they're not being billed for it.&lt;/p&gt;

&lt;p&gt;Most DIY spend-limit code picks one answer implicitly and never surfaces it as a decision — usually by accident, whichever way the meter happens to be wired. It's the kind of bug that doesn't show up until a customer emails asking why their "free" credits triggered a spending block.&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;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCustomerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cap_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_overage_cap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overage_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ignore_grants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// spend covered by an active credit grant doesn't count&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ignore_grants: true&lt;/code&gt; means the cap only tracks spend the customer is actually being billed for. Flip it off and grant-covered usage counts too, useful if the cap is really a margin guardrail rather than a customer-facing promise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Edge 3: Independent reset schedules
&lt;/h2&gt;

&lt;p&gt;Plans reset monthly. Caps often need to reset on a completely different cadence, a $15 weekly guardrail layered on top of a $50 monthly plan limit, for instance. If your reset logic is a single cron job that zeroes out "the counter," you don't have two limits, you have one limit with an identity crisis.&lt;/p&gt;

&lt;p&gt;Caps in Limitr carry their own reset schedule, independent of the plan or credit they're watching:&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;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCustomerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cap_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_weekly_guardrail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overage_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reset_sch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weekly:mon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// resets every Monday&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That weekly guardrail and the customer's monthly plan meter now tick independently, on their own clocks, without needing to know about each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this looks like end to end
&lt;/h2&gt;

&lt;p&gt;Here's the shape of it, a customer on a plan with included Claude usage on a custom price, a monthly overage cap that ignores promo credits, and a tighter weekly guardrail underneath it:&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;// npm i @formata/limitr&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Limitr&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@formata/limitr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// JSON, YAML, TOML, or STOF (default)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
policy: {
    credits: {
        claude_sonnet_4: {
            description: 'Claude Sonnet 4 token'
            overhead_cost: 1.5e-7
            price: { amount: 0.0003 }
        }
    }
    plans: {
        starter: {
            label: 'Starter Plan'
            entitlements: {
                ai_chat: {
                    description: 'AI chat feature'
                    limit: {
                        credit: 'claude_sonnet_4'
                        mode: 'soft'  // allow overage &amp;amp; send overage events
                        value: 16667  // ~$50 included at $0.0003/token
                        resets: true
                        reset_sch: 'monthly:1'
                    }
                }
            }
        }
    }
}`&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;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Limitr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jane@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// $20/month overage cap - doesn't count included usage or promo credits&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCustomerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cap_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_overage_cap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overage_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ignore_grants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reset_sch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monthly:1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// $15/week guardrail - independent clock, same overage-only logic&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCustomerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cap_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_weekly_guardrail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;overage_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ignore_grants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reset_sch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weekly:mon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Spend! Call into LLMs, upload files, run GPU jobs - Limitr handles it all&lt;/span&gt;
&lt;span class="c1"&gt;// Vendor and price agnostic - change in the config without touching code&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6420&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// within plan + caps, allowed and recorded&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// spend capped, hard limit hit, usage governed, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Get current state information&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;customerCap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cus_123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai_overage_cap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Current customer overage (USD): $&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;meter_value&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three flags, two independent clocks, one call to &lt;code&gt;allow()&lt;/code&gt;. Everything upstream of that call — plan boundaries, grant interactions, reset timing — is already resolved by the time you get a yes or no.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three easy decisions, one hard system
&lt;/h2&gt;

&lt;p&gt;Each of those flags is a seemingly five-minute internal conversation on its own with a clear answer in the moment. Overage-only or total? Grants in or out? Reset on its own clock or the plan's?&lt;/p&gt;

&lt;p&gt;But in a real system, both sides of each question turn out to have a real customer behind them, and reversing a decision later isn't free. Flip &lt;code&gt;overage_only&lt;/code&gt; after an enterprise customer is already under contract, and you've quietly changed what they agreed to pay for. Ship the wrong &lt;code&gt;ignore_grants&lt;/code&gt; default, and support finds out from an angry email, not a design review.&lt;/p&gt;

&lt;p&gt;There's more to spend than a single dollar figure, too. Vendors don't all meter the same way, and mapping tokens, GPU-seconds, and flat fees onto one number is its own can of worms. That's a topic for another post.&lt;/p&gt;

&lt;p&gt;If you're building metered AI features and want to poke at this yourself, make sure to check out &lt;a href="https://docs.limitr.dev/" rel="noopener noreferrer"&gt;Limitr&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>We Deserve Better Than JSON as a DSL</title>
      <dc:creator>CJ Cummings</dc:creator>
      <pubDate>Mon, 30 Mar 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/cjcummings/we-deserve-better-than-json-as-a-dsl-13eh</link>
      <guid>https://dev.to/cjcummings/we-deserve-better-than-json-as-a-dsl-13eh</guid>
      <description>&lt;p&gt;It always starts innocently, you're creating a new config or endpoint with some dynamic behavior, thinking "KISS - Keep It Stupidly Simple". What's simpler than JSON or TOML? Some key-value pairs, maybe some nesting, we'll actually keep it clean this time.&lt;/p&gt;

&lt;p&gt;Any experienced programmer knows what comes next.&lt;/p&gt;

&lt;p&gt;Six months later you're hunting for a &lt;code&gt;$ref&lt;/code&gt; in a sea of JSON, writing helper tools, trapped under a stack of legacy decisions, full of regret.&lt;/p&gt;

&lt;p&gt;I've done it. You've done it. The entire industry has done it. GitHub Actions is YAML with a custom expression language bolted on. Terraform invented HCL because JSON wasn't expressive enough. OpenAPI is JSON Schema with extensions piled on top. Every AI framework has its own JSON-based tool definition format that's slightly different from the others.&lt;/p&gt;

&lt;p&gt;The problem isn't the formats. JSON, YAML, TOML - they're all fine at what they do. The problem is that we keep asking them to carry logic they were never designed to hold, then building increasingly elaborate scaffolding when they inevitably buckle.&lt;/p&gt;




&lt;h2&gt;
  
  
  What if your data could just do what's needed?
&lt;/h2&gt;

&lt;p&gt;Here's the part that made me want to build &lt;a href="https://stof.dev" rel="noopener noreferrer"&gt;Stof&lt;/a&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stofAsync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@formata/stof&lt;/span&gt;&lt;span class="dl"&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;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stofAsync&lt;/span&gt;&lt;span class="s2"&gt;`
    name: 'Stof'

    fn loaded() -&amp;gt; str {
        const stof = await Ext.fetch();
        parse(stof, self);
        self.say_hello()
    }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`fn say_hello() -&amp;gt; str {
        'Hello, ' + (self.name ?? 'World') + '!'
    }`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  &lt;span class="c1"&gt;// Hello, Stof!&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The document starts without a &lt;code&gt;say_hello&lt;/code&gt; function. It fetches more Stof from somewhere, an API, another service, an agent, then parses it into itself and calls the function that just arrived.&lt;/p&gt;

&lt;p&gt;Stof runs in a WASM sandbox built in Rust and is just a document of data, like JSON (actually a superset of JSON). It can't touch your filesystem, network, or memory unless you explicitly bridge it to the host environment with &lt;code&gt;doc.lib()&lt;/code&gt;. You control exactly what the context can reach.&lt;/p&gt;

&lt;p&gt;This means a service can share its capabilities as Stof. Not a description of what it can do, but the actual logic. The consumer parses it into context and starts using it immediately, no client library, no SDK, no redeployment. Your system ships with certain capabilities and gains more at runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  The whole picture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://stof.dev" rel="noopener noreferrer"&gt;Stof&lt;/a&gt; is a superset of JSON, so your existing data is already valid, but with functions, types, unit conversions, and async execution built into the format itself instead of a layer on top.&lt;/p&gt;

&lt;p&gt;Instead of trying to replace existing interchange formats, Stof is the glue layer that works with all of them. Parse JSON, YAML, TOML, STOF, etc. into a single document at any time, add the logic that belongs, and send it anywhere. Export portions to the format your app expects internally.&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;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stofAsync&lt;/span&gt;&lt;span class="s2"&gt;`
#[type]
Server: {
    port: 8080
    host: 'localhost'
    secure: false
    MiB memory: 500GiB

    fn url() -&amp;gt; str {
        let url = self.secure ? 'https://' : 'http://';
        url += self.host + ':' + self.port;
        url
    }
}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Parse JSON, YAML, TOML, binary, or more Stof into the same document&lt;/span&gt;
&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server "prod": {
    "host": "prod.example.com",
    "port": 443,
    "secure": true,
    "memory": "2GB"
}`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod.url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// https://prod.example.com:443&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod.memory&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;     &lt;span class="c1"&gt;// ~1907 MiB (auto-converted from GB)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="cm"&gt;/*
host = "prod.example.com"
port = 443
secure = true
memory = 1907.3486328124998   # MiB
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Server&lt;/code&gt; type defines shape, defaults, and behavior. When you parse new data in (JSON, YAML, TOML, whatever) and cast it to that type, it gets the functions and validation for free.&lt;/p&gt;




&lt;h2&gt;
  
  
  Schemas that don't drift
&lt;/h2&gt;

&lt;p&gt;You know what's worse than writing a JSON Schema? Keeping it in sync with the thing it validates.&lt;/p&gt;

&lt;p&gt;Here's the JSON Schema for a simple server config:&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;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://json-schema.org/draft-07/schema#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"port"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"exclusiveMinimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;65536&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;"address"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"minLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="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;"memory"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Memory in MB, must be at least 256"&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;"required"&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;"address"&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;That's a separate file, a separate format, a separate thing to maintain. And notice that &lt;code&gt;memory&lt;/code&gt;, because JSON Schema has no concepts of units, the best you can do is write a comment and hope the user reads it. The validation logic for that field lives somewhere else entirely, probably in your application code.&lt;/p&gt;

&lt;p&gt;In Stof, validation lives on the fields themselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[type]&lt;/span&gt;
&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[schema((target_val:&lt;/span&gt; &lt;span class="nd"&gt;int):&lt;/span&gt; &lt;span class="nd"&gt;bool&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;target_val&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nd"&gt;target_val&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;

    &lt;span class="nd"&gt;#[schema((target_val:&lt;/span&gt; &lt;span class="nd"&gt;str):&lt;/span&gt; &lt;span class="nd"&gt;bool&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;target_val&lt;/span&gt; &lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;

    &lt;span class="nd"&gt;#[schema((target_val:&lt;/span&gt; &lt;span class="nd"&gt;MiB):&lt;/span&gt; &lt;span class="nd"&gt;bool&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;target_val&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="nd"&gt;MB)]&lt;/span&gt;
    &lt;span class="n"&gt;MiB&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;GB&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A port between 1024 and 65536, a non-empty address, and at least 256MB of memory. The last one is meaningful because Stof understands units as types, so pass &lt;code&gt;"2GB"&lt;/code&gt; and it converts, pass in &lt;code&gt;"100MB"&lt;/code&gt; and it fails. The schema can't drift from the data because it &lt;em&gt;is&lt;/em&gt; the data.&lt;/p&gt;




&lt;h2&gt;
  
  
  A real production use case
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://limitr.dev" rel="noopener noreferrer"&gt;Limitr&lt;/a&gt; is an open source pricing and enforcement engine built on Stof. The entire policy, plans, credits, limits, validation logic, lives in a single Stof document. It's a good example of what "data that carries its own logic" looks like when it gets past the toy stage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Give it a try
&lt;/h2&gt;

&lt;p&gt;The fastest way in is the &lt;a href="https://play.stof.dev" rel="noopener noreferrer"&gt;playground&lt;/a&gt;, runs in your browser via WASM, no install needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @formata/stof      &lt;span class="c"&gt;# TypeScript/JavaScript&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;stof         &lt;span class="c"&gt;# Python&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;stof-cli   &lt;span class="c"&gt;# CLI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.stof.dev" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; - reference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dev-formata-io/stof" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; - source and issues&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discord.gg/Up5kxdeXZt" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; - come tell us about your use case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's also a &lt;a href="https://marketplace.visualstudio.com/items?itemName=Formata.stof" rel="noopener noreferrer"&gt;VSCode extension&lt;/a&gt; for Stof syntax highlighting.&lt;/p&gt;

&lt;p&gt;Apache 2.0.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
