<?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>Forem: Kenneth Mckrola</title>
    <description>The latest articles on Forem by Kenneth Mckrola (@mackoverflow).</description>
    <link>https://forem.com/mackoverflow</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3891762%2F6c560b7e-4be6-467c-b325-df54e6e8cda4.jpg</url>
      <title>Forem: Kenneth Mckrola</title>
      <link>https://forem.com/mackoverflow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mackoverflow"/>
    <language>en</language>
    <item>
      <title>Easily benchmark all your app's endpoints at once</title>
      <dc:creator>Kenneth Mckrola</dc:creator>
      <pubDate>Wed, 29 Apr 2026 21:09:11 +0000</pubDate>
      <link>https://forem.com/mackoverflow/easily-benchmark-all-your-apps-endpoints-at-once-2fod</link>
      <guid>https://forem.com/mackoverflow/easily-benchmark-all-your-apps-endpoints-at-once-2fod</guid>
      <description>&lt;p&gt;Most "load tests" in real codebases are a &lt;code&gt;curl&lt;/code&gt; pasted into a Slack thread. Someone runs it before a release, eyeballs the latency, and we ship. There's nothing version-controlled, nothing repeatable, and the next person to touch the service has no idea which endpoints are actually fast paths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://benchmarkr-1.onrender.com" rel="noopener noreferrer"&gt;benchmarkr&lt;/a&gt; is a powerful and easy-to-use CLI and MCP tool that fixes that part of the workflow specifically. The thing I want to talk about in this post is the piece that makes it click: a YAML config that lives in your repo and describes every endpoint you care about, the same way a &lt;code&gt;package.json&lt;/code&gt; describes your dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The config
&lt;/h2&gt;

&lt;p&gt;First, install benchmarkr cli if you haven't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap mack-overflow/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;benchmarkr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for Homebrew, or for Debian&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [trusted=yes] https://apt.fury.io/mack-overflow/ /"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/benchmarkr.list
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;benchmarkr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(More installation guides available &lt;a href="https://benchmarkr-1.onrender.com/docs" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Next, run &lt;code&gt;benchmarkr endpoints init&lt;/code&gt; in your project root and you get a &lt;code&gt;benchmarkr.yaml&lt;/code&gt; you can commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;list-users&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${API_BASE:-http://localhost:8080}/users&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bearer ${API_TOKEN}&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
      &lt;span class="na"&gt;duration_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;search-users&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${API_BASE}/users/search&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;q&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test"&lt;/span&gt;
      &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50"&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
      &lt;span class="na"&gt;duration_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;create-order&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${API_BASE}/orders&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bearer ${API_TOKEN}&lt;/span&gt;
      &lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ABC-123"&lt;/span&gt;
      &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
      &lt;span class="na"&gt;duration_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Env var substitution.&lt;/strong&gt; &lt;code&gt;${API_BASE}&lt;/code&gt; and &lt;code&gt;${API_BASE:-default}&lt;/code&gt; work the way they do in shell. A sibling &lt;code&gt;.env&lt;/code&gt; file is auto-loaded but never overrides what's already in the environment, so the same file works on a laptop, in CI, and in staging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defaults travel with the endpoint.&lt;/strong&gt; &lt;code&gt;create-order&lt;/code&gt; runs at concurrency 2 for 10 seconds because that's what makes sense for a write path. &lt;code&gt;list-users&lt;/code&gt; runs at concurrency 10. You set this once in the file you already review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery walks up from CWD.&lt;/strong&gt; Run the CLI from any subdirectory and it finds the file, like &lt;code&gt;git&lt;/code&gt; does.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Running one endpoint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="nt"&gt;-e&lt;/span&gt; list-users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Saved defaults apply. Any flag you pass on the command line wins; headers and params are merged. So when you're poking at production specifically, you can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="nt"&gt;-e&lt;/span&gt; list-users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"X-Trace: debug-2026-04-28"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt; 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…without editing the committed file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running all of them
&lt;/h2&gt;

&lt;p&gt;This is where the YAML pays for itself. Because every endpoint is named and self-describing, you can hand the entire file to the CLI in one shot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That walks every endpoint in &lt;code&gt;benchmarkr.yaml&lt;/code&gt; in succession, applying each endpoint's saved defaults (concurrency, duration, headers, body — the whole config). Between runs you get a &lt;code&gt;[i/N] &amp;lt;name&amp;gt;&lt;/code&gt; header so it's obvious where you are; live p50/p95/p99 streams in for the active endpoint and a final summary prints when it finishes. &lt;code&gt;--all&lt;/code&gt; is mutually exclusive with &lt;code&gt;--url&lt;/code&gt; and &lt;code&gt;--endpoint&lt;/code&gt;, and any flags you do pass (e.g. &lt;code&gt;--store&lt;/code&gt;, &lt;code&gt;--json&lt;/code&gt;, &lt;code&gt;--rate-limit&lt;/code&gt;) apply to every run in the sweep.&lt;/p&gt;

&lt;p&gt;For CI, this collapses the workflow step to one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/perf.yml&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Benchmark every endpoint&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;API_BASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.staging.example.com&lt;/span&gt;
    &lt;span class="na"&gt;API_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.STAGING_API_TOKEN }}&lt;/span&gt;
    &lt;span class="na"&gt;BENCH_CLOUD_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.BENCHMARKR_TOKEN }}&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;benchmarkr run --all --store --json &amp;gt; perf-results.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--json&lt;/code&gt; with &lt;code&gt;--all&lt;/code&gt; emits an array — one entry per endpoint, with the same &lt;code&gt;result&lt;/code&gt; shape as a single run — so you can pipe it straight into a regression check or upload it as a CI artifact:&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="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;"list-users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stop_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30.001s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stored"&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;"result"&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;"requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12483&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p50_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p95_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p99_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;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;"search-users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stop_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15.002s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stored"&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;"result"&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;"requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4127&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p50_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p95_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p99_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;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;"create-order"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stop_reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10.001s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stored"&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;"result"&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;"requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;312&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p50_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p95_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"p99_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;121&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"errors_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;You're not maintaining a separate list of "endpoints to benchmark" in your CI workflow and a list in your config. There's one list. Add a new endpoint to &lt;code&gt;benchmarkr.yaml&lt;/code&gt; in the same PR that adds the route, and the next CI run picks it up automatically — no workflow edits, no shell loop to babysit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round-tripping with the cloud dashboard
&lt;/h2&gt;

&lt;p&gt;The CLI gives you fast feedback. The dashboard gives you the long view — historical p95 charts, regression detection across versions, the kind of thing that's painful to wire up yourself.&lt;/p&gt;

&lt;p&gt;The newest piece is import/export, so the YAML in your repo and the endpoints in the dashboard stay in sync without anyone having to maintain both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export from the dashboard.&lt;/strong&gt; Open any endpoint and click &lt;strong&gt;Export&lt;/strong&gt; for YAML or JSON. Or click &lt;strong&gt;Export all&lt;/strong&gt; in the endpoints nav to dump every endpoint to one file you can drop into a fresh repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Import to the dashboard.&lt;/strong&gt; Click &lt;strong&gt;Import&lt;/strong&gt;, pick a &lt;code&gt;benchmarkr.yaml&lt;/code&gt;, and endpoints upsert by &lt;code&gt;(user, name)&lt;/code&gt;. If the config changed, a new version is recorded — so you get a history of how each endpoint's load shape evolved.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2klkwgl4a48htpx3lg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2klkwgl4a48htpx3lg2.png" alt="Import in Benchmarkr UI Nav" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fochel2kdfj1i2qvfo1up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fochel2kdfj1i2qvfo1up.png" alt="Export as YAML in UI" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;A workflow I've been using:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define endpoints in &lt;code&gt;benchmarkr.yaml&lt;/code&gt;, commit them.&lt;/li&gt;
&lt;li&gt;CI runs the loop above on every PR with &lt;code&gt;--store&lt;/code&gt; and the cloud token, persisting results to the dashboard.&lt;/li&gt;
&lt;li&gt;Open the endpoint in the dashboard to see the trend line for that endpoint across the last N PRs.&lt;/li&gt;
&lt;li&gt;If somebody adds an endpoint via the dashboard UI for ad-hoc poking, &lt;strong&gt;Export&lt;/strong&gt; → drop the file into the repo → it's now part of the CI matrix.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A note on the cloud dashboard
&lt;/h2&gt;

&lt;p&gt;The cloud platform is currently in &lt;strong&gt;closed beta&lt;/strong&gt;. We're planning to open it up to the public on a per-token basis in &lt;strong&gt;spring 2026&lt;/strong&gt; — if you'd like access at launch, you can &lt;a href="https://benchmarkr-1.onrender.com/waitlist" rel="noopener noreferrer"&gt;join the waitlist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The CLI itself is open source and works without the cloud — &lt;code&gt;benchmarkr run&lt;/code&gt;, the YAML config, and even local result persistence don't require an account or a token. The dashboard, history charts, version pinning, and import/export are the parts gated behind beta access for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is worth doing
&lt;/h2&gt;

&lt;p&gt;The shift that matters isn't "run benchmarks in CI" — plenty of tools do that. It's having a single, reviewable file that says &lt;em&gt;here are this service's endpoints and how we expect them to behave under load&lt;/em&gt;, sitting next to the code in the same PR.&lt;/p&gt;

&lt;p&gt;Once that file exists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New endpoints get a perf budget at the same moment they get a route handler.&lt;/li&gt;
&lt;li&gt;Reviewers can see in the diff that a new write path is being benchmarked at concurrency 2, not 100, and push back if that's wrong.&lt;/li&gt;
&lt;li&gt;CI gets a free regression signal across every endpoint, not just the one someone remembered to add to a script.&lt;/li&gt;
&lt;li&gt;The dashboard gives you the historical view without anyone manually re-entering endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repo already describes your API. This is just letting it benchmark itself.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;benchmarkr is open source — &lt;code&gt;brew install mack-overflow/tap/benchmarkr&lt;/code&gt; or grab it from &lt;a href="https://benchmarkr-1.onrender.com" rel="noopener noreferrer"&gt;benchmarkr&lt;/a&gt;. Cloud dashboard beta access opens publicly per-token in spring 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>performance</category>
      <category>devops</category>
      <category>go</category>
    </item>
    <item>
      <title>Benchmarkr - cURL, built for concurrency, MCP, and real performance benchmarking</title>
      <dc:creator>Kenneth Mckrola</dc:creator>
      <pubDate>Wed, 22 Apr 2026 06:48:19 +0000</pubDate>
      <link>https://forem.com/mackoverflow/benchmarkr-curl-built-for-concurrency-mcp-and-real-performance-benchmarking-17c6</link>
      <guid>https://forem.com/mackoverflow/benchmarkr-curl-built-for-concurrency-mcp-and-real-performance-benchmarking-17c6</guid>
      <description>&lt;p&gt;&lt;a href="https://benchmarkr-1.onrender.com" rel="noopener noreferrer"&gt;Link to benchmarkr homepage&lt;/a&gt;&lt;br&gt;
What if cURL let you easily run concurrent requests and benchmark your&lt;br&gt;
endpoints? Where you had an executable that exports tools for your coding&lt;br&gt;
agents (Claude, Cursor) via MCP, streams live performance updates, and&lt;br&gt;
auto-exports benchmark runs to JSON or SQL?&lt;/p&gt;

&lt;p&gt;Development speed is increasing rapidly. Testing and benchmarking are&lt;br&gt;
becoming even more crucial aspects of development for testing AI-generated&lt;br&gt;
and AI-assisted code. &lt;strong&gt;Benchmarkr&lt;/strong&gt; lets you easily orchestrate performance&lt;br&gt;
testing on your API endpoints — whether you're catching regressions, sanity-&lt;br&gt;
checking a refactor, or letting an agent validate the code it just wrote&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p6w5nk7dy48ep4t7sli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p6w5nk7dy48ep4t7sli.png" alt="Hero image of benchmarkr run" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why another HTTP tool?
&lt;/h2&gt;

&lt;p&gt;There's no shortage of load-test tools — &lt;code&gt;hey&lt;/code&gt;, &lt;code&gt;ab&lt;/code&gt;, &lt;code&gt;wrk&lt;/code&gt;, &lt;code&gt;bombardier&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;k6&lt;/code&gt;. They're great at what they do, but they live in a pre-agent world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No live feedback&lt;/strong&gt; — you wait 30 seconds, then read a wall of text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No structured persistence&lt;/strong&gt; — you pipe to a file, grep, repeat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No agent integration&lt;/strong&gt; — your coding agent can't call them without
shelling out and parsing free-form output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmarkr is a single Go binary that does three things well with little out of the box configuration required:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs concurrent HTTP benchmarks with live metrics in the terminal.&lt;/li&gt;
&lt;li&gt;Stores runs as JSON files, Postgres, or MySQL — configured once, reused
forever.&lt;/li&gt;
&lt;li&gt;Ships an MCP server so Claude Code, Cursor, and any other MCP-compatible
agent can benchmark your endpoints by name.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/Mack-Overflow/api-bench" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://benchmarkr-1.onrender.com/docs" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS / Linux&lt;/span&gt;
brew tap mack-overflow/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;benchmarkr

&lt;span class="c"&gt;# Debian / Ubuntu&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [trusted=yes] https://apt.fury.io/mack-overflow/ /"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/benchmarkr.list
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;benchmarkr

&lt;span class="c"&gt;# RHEL / Fedora&lt;/span&gt;
&lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/yum.repos.d/benchmarkr.repo &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
[benchmarkr]
name=Benchmarkr
baseurl=https://yum.fury.io/mack-overflow/
enabled=1
gpgcheck=0
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;benchmarkr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or grab a binary from the &lt;a href="https://github.com/Mack-Overflow/api-bench/releases/tag/v0.1.2" rel="noopener noreferrer"&gt;releases page&lt;/a&gt; if you'd&lt;br&gt;
rather skip a package manager.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your first benchmark
&lt;/h2&gt;

&lt;p&gt;The smallest useful command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;benchmarkr run --url https://api.example.com/health&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That fires a single worker for 10 seconds at a GET endpoint. You'll see requests, errors, and P50/P95 update live, then a final summary with throughput, latency percentiles, status-code breakdown, response sizes, and cache hit/miss counts.&lt;/p&gt;

&lt;p&gt;Add concurrency and duration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://api.example.com/users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt; 50 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--duration&lt;/span&gt; 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;POST with headers and a body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://api.example.com/users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--method&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer tok_xxx"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--body&lt;/span&gt; &lt;span class="s1"&gt;'{"name":"test"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rate-limit so you don't accidentally DDoS staging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://api.example.com/search &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--duration&lt;/span&gt; 20 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rate-limit&lt;/span&gt; 100    &lt;span class="c"&gt;# max 100 req/s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bypass the CDN cache to measure origin latency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;benchmarkr run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; https://cdn.example.com/asset.js &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cache-mode&lt;/span&gt; bypass &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--duration&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The MCP server — letting agents benchmark for you
&lt;/h2&gt;

&lt;p&gt;This is the part I'm most excited about. Install the MCP companion binary:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install mack-overflow/tap/benchmarkr-mcp&lt;/code&gt;&lt;br&gt;
Then wire it into your agent. For Claude Code, drop a .mcp.json in&lt;br&gt;
your project root:&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;"mcpServers"&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;"benchmarkr"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"benchmarkr-mcp"&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;And a short CLAUDE.md so the agent prefers it over reinventing the wheel:&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="gh"&gt;# Benchmarking&lt;/span&gt;

Use the benchmarkr MCP tools (run_benchmark, get_benchmark_status,
stop_benchmark, list_endpoints) for all API benchmarking tasks.
Do not install or use external tools like hey, ab, or bombardier.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cursor is the same config under ~/.cursor/mcp.json plus a .cursorrules.&lt;/p&gt;

&lt;p&gt;Now you can say things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Benchmark the /api/users endpoint at 20 concurrent workers for 30
seconds and tell me if the P95 is above 200ms."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and the agent calls the run_benchmark tool directly, reads the&lt;br&gt;
structured result, and answers in the context of your actual code. No more&lt;br&gt;
"let me write a shell script for you" dance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedy55l177m6bjfy96ssq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedy55l177m6bjfy96ssq.png" alt="Claude benchmarkr mcp run" width="616" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is heading
&lt;/h2&gt;

&lt;p&gt;A few things on the roadmap I'm looking for feedback on:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;compare_endpoints&lt;/code&gt; — run two URLs side-by-side and diff the metrics.&lt;br&gt;
&lt;code&gt;regression_test&lt;/code&gt; — assert against a previous run's P95/P99 and return a pass/fail the agent can reason about.&lt;br&gt;
Scenario files — YAML-defined multi-step flows (login → fetch → post) instead of single-URL runs.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>performance</category>
      <category>go</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
