# Dispatch Studio — Call the API. Then watch what it did.

Dispatch Studio is a desktop **API workspace** with a **load tester** and a **JVM monitor** in the same window. Scan a service, call it, put the calls in a suite and then under load — and switch to Observe to see the query it fired, the queue it published to, the log line it wrote and the object it left on the heap. A **desktop agent** does the steps no API reaches, and **AI Ground** answers questions about all of it with a model on your own computer.

Runs on your machine · No account, no server, no sync · Watches Java 8 and up

![Dispatch Studio in Observe: web transactions for a bookstore service, the busiest endpoint opened to its latency over the window and its percentiles, and an Insights panel breaking GET /api/books/:id down into BookController#get, ViewCache#get, ViewStatsRepository#recordView and ViewEvents#published.](https://studio-dispatch.com/assets/15-apm-endpoint-insights.webp)

Web transactions for a running Spring Boot service, with **Insights** open on one endpoint: where the time goes inside the handler, method by method.

## Build: An API workspace that starts from your code

Scan a source tree into catalogs, send any protocol, keep secrets in the OS keystore, and commit suites to your repository.

- Scan a project
- Import
- Catalogs
- Environments
- Suites
- Fake API
- API documentation
- History

## Load: Load tests made of the same requests

Turn the calls you built into a test plan, run it against an environment that allows it, and read what held and what bent — on a schedule if you like, with rules for what happens after.

- Test plans
- Passes when
- Schedules
- After the run
- Compare runs
- PDF and Excel reports

## Observe: A JVM monitor behind the same requests

One `-javaagent` flag on the service and the screens fill in: per-endpoint percentiles, the JDBC and broker calls behind them, the log, the live JVM, and heap dumps down to the object holding the memory.

- Overview
- Web transactions
- Background jobs
- Errors
- Data stores
- Messaging
- External calls
- Logs
- Live JVM
- Heap dumps
- Alerts

## Workflows: A desktop agent for the steps no API reaches

Write the task in your own words. The agent works through it with the mouse and keyboard, a step at a time, each step with its own limit, and stops the moment you tell it to.

- Agents
- Steps and tries
- Claude or a local model
- Run history

## AI Ground: Questions answered on your own computer

Ask about your plans, runs, suites and catalogs, and read the answer beside the records it came from. The model runs in Ollama; nothing is sent anywhere.

- Local model
- Cited records
- Make me a plan
- Forget everything indexed

## For a team: An APM server of your own

For staging and production, run the APM server on your own hardware or in your own AWS account, and connect everyone's Studio to it.

- Docker Compose
- systemd
- One EC2 instance
- Multi-AZ on AWS

## Build: Start from the code, not from a blank request

Most API tools begin with an empty request and a URL you have to remember. Dispatch reads the routes out of the service's own source and hands you a catalog you can send straight away.

### Scan a project: Point it at a folder. Get every endpoint.

No running service and no OpenAPI document: **Scan a project** reads the controllers, works out the framework, and generates request bodies from the types the handlers take.

| Language | Frameworks |
| --- | --- |
| Java | Spring Boot, Play, JAX-RS, Quarkus, Micronaut |
| .NET | ASP.NET Core controllers and minimal APIs |
| Go | Gin, Echo, Fiber, Chi, Gorilla mux, net/http |
| Python | FastAPI, Flask, Django |

![The Scan a project wizard at its Endpoints step: ten endpoints found in a Spring Boot service, grouped into Auth, Authors, Books and Health, with the generated JSON body for POST /api/auth/login.](https://studio-dispatch.com/assets/05-scan-endpoints.webp)

Ten endpoints from a Spring Boot bookstore, each with the file and line it came from and a body generated from its request type.

![Scan a project asking which of two frameworks found in the folder the service uses, with Spring Boot marked likely.](https://studio-dispatch.com/assets/02-scan-stack-detect.webp)

**It asks when the code is ambiguous** A folder with both Spring and JAX-RS annotations gets a choice, with the likelier one marked.

![Import options: one catalog per resource grouped by URL, one per controller, or one for everything.](https://studio-dispatch.com/assets/06-scan-catalogs.webp)

**Catalogs the way you think of the API** One per resource, one per controller, or one for everything.

![A rescan reporting nothing new: every endpoint it found is already in the project.](https://studio-dispatch.com/assets/04-scan-rescan-delta.webp)

**A rescan shows what changed** Only what is new is offered — here nothing, all ten are already in the project — and the bodies and assertions you added stay put.

### Send: Every protocol in one pane

HTTP, GraphQL, WebSocket, server-sent events and gRPC share the same request pane; what changes is the middle. JSON is validated as you type, and the response shows its timing broken into DNS, TCP, TLS, first byte and download.

- **Auth once, on the catalog:** bearer, basic, API key or OAuth 2, inherited by every request in it.
- **Path variables apart from query:** `/books/{id}` and `?id=` are different things, so a catalog can be re-pointed.
- **The response in five tabs** — body, headers, tests, a diff and a console that shows what a script logged. Select a value in the body and **Save to variable** puts it in an environment.
- **Copy as code** in cURL, JavaScript, Python, Go, Java and C#.

![A POST to create a book with a JSON body, answered 201 in 171 ms with the created record shown as a JSON tree.](https://studio-dispatch.com/assets/01-request-response.webp)

A `POST` built from the scan, answered 201 in 171 ms, the response as a tree you can query with JSONPath.

### Environments: Secrets stay in the keystore

A variable is `{{name}}`. Environments belong to the project and carry a colour, so production never looks like local. A variable marked **secret** lives in Windows Credential Manager — never in the workspace file, a backup, or the clipboard.

**Copy as cURL** and **Copy as code** write `{{name}}` in its place, so what you share keeps its structure and none of its secrets. Each environment also says whether load tests may run against it; none may until you allow it.

![The Environments dialog with Local and Staging environments; apiToken is marked secret and shown masked.](https://studio-dispatch.com/assets/09-environments.webp)

Globals and per-project environments; `apiToken` is secret and never written to the workspace file.

### Tests and chaining: Checks you can read, scripts when you need them

Assertions are declarative — status, time, a header, a JSONPath, the body — each with an operator and a value. Pre-request and post-response scripts handle what assertions cannot say: signing a request, computing a nonce, lifting a token out of a response for the next call.

Chaining is by name: a step in a suite reads the status, a header or the body of any step that already ran, as `{{steps.post login.body.$.token}}`.

### Suites: Tests that live in your repository

A suite is setup, steps and teardown as a YAML file in your own repository, under `.dispatch/suites/`. It is reviewed in a pull request and travels with the branch. It is also how requests are put in order: a step reads any earlier step's response by its name, defaults are sent with every step, and **Stop at the first failure** does what it says. **Diagram** draws the steps and where each value comes from.

The Chrome extension records a real session — log in, do the thing, stop — and hands back a draft you review before it becomes a suite.

![A suite named Book catalogue smoke test with two steps, both passed in 17 ms, stored as a YAML file under .dispatch/suites.](https://studio-dispatch.com/assets/11-suite-passed.webp)

A two-step smoke test, passed in 17 ms, stored as `.dispatch/suites/Book catalogue smoke test.yaml`.

### Import

An OpenAPI or Swagger document from a URL or a file, a Postman collection, a HAR, or one pasted cURL command — into a catalog you can send straight away.

### Fake API

A local server on a port you choose, answering with the responses you recorded, so front-end work is not blocked on a service that does not exist yet. It never leaves your machine.

### API documentation

Documentation generated from your catalogs, and copied out as Markdown.

### History

Every request you send, with its response, per project, across restarts.

### The assistant

Bring your own Anthropic key: the assistant explains a response and suggests tests for it. It asks before anything is sent, and Settings says exactly what it sends and what it holds back.

### Command palette

Ctrl K for the rest: scan, import, environments, the Fake API, copying a request as code, generating the documentation, the theme.

## Load: Then find out how much it takes

The requests you built are the load test. A plan is a file in the repository beside the suites, it runs only against an environment that allows it, and it ends with a verdict against conditions you set before it started.

### Test plans: Five steps, one file

A plan is written in five steps down the side of the editor — **The numbers**, **Once at the start**, **Main**, **Passes when** and **After the run** — and saved as `.dispatch/load/<name>.yaml`. Choose **Smoke** to ask whether it works at all, or **Load** to ask whether it holds a busy day, bends, or leaks over hours.

- **The numbers:** users at once, ramp-up, a duration or a number of rounds, a pause between calls, and a fixed request rate when you want one.
- **Once at the start** runs once for each user — signing in, usually; **Main** is what each user repeats, in weighted scenarios. Bring in a whole suite or a recording, and give each user values of its own from a CSV or JSON file.
- **Passes when** is picked, not typed: a measure, a comparison and a number, such as p95 below 500 ms.

### The run: What held, what bent, and what the server saw

A run draws response time as the users ramp up, requests a second and errors, then a table for each API and a verdict against the plan's own conditions. It also says whether this computer kept up: a load generator that cannot keep pace is measuring itself, not your service.

With Observe connected, **On the server** shows what the application was doing while the run went on.

- **Compare runs**, or set one run beside any earlier one. The newest 50 runs of each plan are kept.
- **A report of any run** as PDF, as an Excel workbook — summary, pass conditions, each API, over time, first failures — or as HTML.
- **Requests to read one by one:** the first 500 of a run, and up to 500 failures.

### Safe by default

A plan is pinned to one environment, and that environment must allow load tests. One named like production asks for its name to be typed before every run, and is never run on a schedule.

### On a schedule

Every day, or on the days you choose, at a set time. The computer is kept awake from ten minutes before until the run ends. Studio has to be open — minimised is fine — and a missed run is written into the list rather than run late.

### After the run

Rules such as *if the run fails, notify me*, or *if p95 is worse than last run, run an agent* with the run's figures filled in. Each run's report can be saved as PDF or Excel into one folder for passed runs and another for failed ones.

## Observe: Then switch to Observe

The request you just sent and the database call it caused are the same event. Reading them in two tools means correlating by timestamp and hope — so the monitor is in the same window, behind the same requests. [How it connects](https://studio-dispatch.com/#how)

### Web transactions: Percentiles that keep the tail

Every endpoint's throughput and latency — p90, p95, p99 and the worst call — from histograms recorded per call inside the JVM and summed, never averaged across a window. The tail survives the trip to the desktop. Open an endpoint for its own history, with every collector stop marked under its latency.

Endpoints the scan found but nobody called are listed too, so **No traffic** is an answer rather than an absence.

![Web transactions: ten endpoints in source, seven taking traffic, three with none, and a table of requests, rate, p99 latency and errors per endpoint.](https://studio-dispatch.com/assets/14-apm-web-transactions.webp)

Ten endpoints in the source, seven taking traffic, three with none.

### Detailed analysis: Where the time goes inside a handler — when you ask

Endpoint metrics are always on and cost next to nothing. Seeing inside a handler means sampling the threads serving requests, so it runs only when someone asks, for five minutes, and stops on its own.

![The Insights panel for GET /api/books/:id offering to run detailed analysis for five minutes.](https://studio-dispatch.com/assets/16-apm-analysis-optin.webp)

Insights offers the sampling; nothing is sampled until someone presses the button.

### Several applications: One receiver, every service

Each application registers with its own key and reports on its own. Switch between them in the Observe column; each keeps its own history, errors and log.

![Observe with two applications in its column, Bookstore and Checkout service, and the bookstore's overview: requests, throughput, its busiest and slowest endpoints, and response time split by where it was spent.](https://studio-dispatch.com/assets/19-apm-app-bookstore.webp)

Two applications on one receiver; the bookstore is selected.

### Live JVM: What the process is doing right now

The Runtime screens read the JVM behind the traffic. **Findings** opens on what is wrong now — threads deadlocked, a heap that is not coming back down, old collections costing more than young ones, a pool nearly full — each one linked to the screen that shows it.

- **Collections:** every stop, newest first, with the median, the 95th and 99th percentiles and the longest. A concurrent cycle runs beside the application, so it is counted as a cycle, not a stop.
- **Threads:** thread dumps, or three of them five seconds apart to find the ones that are stuck, with saturated pools and the thread holding a lock the others wait on.
- **Memory pools, Leak suspects, Allocation trace** and a five-minute **CPU profile**. The agent can be attached to a JVM already running on this machine.

![Observe's Findings for the bookstore: two JVMs on this machine, both reporting, the agent found, and What's wrong now reading nothing found, with the two checks that could not run yet.](https://studio-dispatch.com/assets/28-jvm-findings.webp)

Findings for the bookstore's two JVMs: nothing above the reporting threshold, and what could not be checked yet.

### Heap dumps: Who is holding the memory, and why it is still alive

Open an `.hprof` file, or send one straight from **Objects on the heap**, and the APM server analyses it — the parsing happens there, not on your desktop. The **Dominator tree** shows what each object owns: what only it keeps alive, biggest first, where retained is what would be freed if it went.

**Why is it alive?** walks the path from a GC root to the object, field by field, with weak, soft and phantom references left out unless you ask for them, the root's kind spelled out — a local variable on a thread's stack, a class the JVM itself keeps loaded — and any static field on the way named. **Compare** sets a dump beside an earlier one: what grew, where the growth is held, and what shrank.

- Overview
- Leak suspects
- Dominator tree
- Biggest objects
- Classes
- Loaders
- Off-heap
- Configuration
- Compare
- Findings

![Leak suspects in a heap dump of the bookstore: DefaultListableBeanFactory retaining 61.5 per cent, ViewAuditService 51.7 per cent with its path through a ConcurrentHashMap, each with a Why is it alive link.](https://studio-dispatch.com/assets/37-heap-dump-leak-suspects.webp)

Leak suspects in a dump of the bookstore, each with the path that keeps it alive.

### Alerts

Rules on what matters — what to watch, the measure, the threshold, the window it is measured over, and how many checks in a row confirm it — delivered to an email list or PagerDuty, each target checked with a test send. A firing alert can be silenced for an hour.

### Hosts

An application on several hosts reads as one, or host by host. The Overview's **By host** table shows each instance's traffic, heap, CPU and last report; one that stopped reporting stays listed, greyed, for 30 days so its logs can still be read.

### What is woven in

Data stores, messaging and external calls can each be switched off while the JVM runs: the woven bytecode comes out and the methods go back to what they were.

## A worked example: Five screens, one leak

Every number here came off a real service — a Spring Boot bookstore on -Xmx256m with an audit cache deliberately left switched on, watched for about fifteen minutes. This is the path the screens walk you down.

### STEP 01 Web transactions: The average is fine. The worst case is not.

GET /api/books/:id answers in under 8 ms ninety-five times out of a hundred. Its slowest call took **2.08 seconds** — two hundred and fifty times its own p95. A mean would have hidden it completely.

GET /api/books/:id · 1,080 calls

mean · 5.88 ms

p95 · 7.94 ms

p99 · 15.80 ms

max · 2,081.50 ms

errors · 103 · 98×404, 5×400

### STEP 02 Data stores: It was not the query. It was getting a connection.

Connection acquisition is its own row. Normally it takes **30 microseconds**. Once it took **2.76 seconds** — which is where the endpoint's 2.08 s went. The row also says where it was called from: 1.64 acquisitions per GET /api/books/:id, the tell for an N+1 before anyone opens a profiler.

jdbc · acquire a connection · 1,913 calls

p50 · 0.030 ms

p99 · 0.97 ms

max · 2,764.06 ms

share of store time · 86.5 %

### STEP 03 Runtime → Collections: Ten collections cost more than a hundred and twenty-six.

A pool stalls when the threads holding connections are stopped. **Ten old-generation pauses took 882 ms**; all **126 young collections together took 647 ms**. Old-generation collections that keep arriving are not a tuning problem — something is surviving them.

G1 Old Generation · 10 pauses · 882 ms

G1 Young Generation · 126 pauses · 647 ms

worst single pause · 130 ms

### STEP 04 Runtime → Leak suspects: What survived: 29 MB of it.

After each major collection the agent takes a class histogram of what is left. Over nine collections byte[] rose in **eight** and gained **29.3 MB** — with 6,773 fewer arrays. Fewer, larger buffers: a cache growing its entries.

byte[] · growth over the window · +29.3 MB

instances · −6,773

rose in · 8 of 9 collections

### STEP 05 Runtime → Objects on the heap: byte[] is not the culprit. This is.

A histogram can only ever say byte[]. Retained size says who would free it: walk the dominator tree and **one application object holds 51.7% of the reachable heap** — a Spring singleton with an unbounded map of view records.

ViewAuditService · retained · 33.8 MB · 51.7 %

held through · ConcurrentHashMap$Node[]

## Reference: Twelve screens, twelve questions

Each answers something people ask out loud during an incident. The Observe column groups them the same way: what the service did, the runtime that did it, and what wakes somebody up.

Overview

Where is the time going, minute by minute?

Request time split across **data stores**, **messaging**, **external** and the application itself, and host by host.

Web transactions

Which endpoint is slow, and how slow at the tail?

Throughput and p90–p99 per endpoint, from summed histograms.

Background jobs

What is running that is not a request?

Schedulers and listeners, each with what its runs spend their time on.

Errors

What is failing, and is it our fault or theirs?

Ranked by severity before volume; red for 5xx, amber for client mistakes.

Data stores

Which query, how often, and called from where?

Every JDBC statement, Redis command and connection-pool wait.

Messaging

Are we keeping up with the queue?

Publish and consume timed apart: RabbitMQ, Kafka, JMS and SQS verified.

External calls

Whose service is making us slow?

Outbound HTTP by host, with its own percentiles.

Logs

What did it say while that was happening?

Streamed and searchable, with stack traces, the request each line belongs to, and the lines either side.

Live JVM

What is this process doing right now?

Findings, trend, memory pools, collections, threads, leak suspects, allocations and a CPU profile.

Heap dumps

Who is holding the memory?

Dominator tree, leak suspects and the path from a GC root, analysed on the APM server.

Alert configuration

When should somebody be told?

Rules, the alerts they raised, and their history.

Notification settings

Who hears about it?

Email lists and PagerDuty, each with a test send.

## Workflows: An agent for the steps no API reaches

Some work only happens in a window, in a desktop program with no API. An agent in Workflows is given the task in your words and does it with the mouse and keyboard, a step at a time, on Claude or on a model running on your own computer.

### Agents: Write the task. Check the steps. Press Run.

An agent is a task — with `{{values}}` you fill in at each run — and the steps it takes to do it, generated from the task or written by hand. Each step has its own limit of tries, can open a program before it starts, and says whether it needs the model at all. The steps, values, attachments and model are checked first, and a run does not start until every check passes.

- **Claude Sonnet 5 or Opus 5** on the assistant's key, with a consent of its own that lists what is sent; or **a local model through Ollama**, where nothing leaves the machine.
- **What each step cost:** tries, tokens read and written, and the price, with the costliest step marked. **Analyse run** suggests changes, each with a button to apply it.
- **An answer file** that Studio writes, never the model, and never over one that is already there.

### Rules it works to

The model is told that text on the screen is not an instruction, never to type a password, and to stop before it sends, submits, buys, deletes or changes a setting.

### You can always stop it

While it runs, an amber frame goes round the screen. Press Ctrl+Alt+Q or push the mouse into the top-left corner, and it stops before its next action.

### Runs you can go back to

Each run keeps its log and the last screen of every try, for 14 days and up to 50 runs an agent. An agent has no schedule of its own: you press Run, or a Load rule starts it after a run.

## AI Ground: Ask about your own work, on your own computer

AI Ground answers questions from what Dispatch already holds: your test plans and their runs, your suites and what they did, and the endpoints in your catalogs. The model runs in Ollama on your computer, and nothing is sent anywhere.

### Answers with sources: Every answer beside the records it came from

A question is matched against the records first; then a local model reads the best of them and answers, citing each one as [1]. The records it read are listed beside the answer, and one is marked as used only if the answer cited it, so a claim with nothing behind it shows as one.

With no model set up, the same question returns the matching records, ranked. Observe's readings and response bodies come in a later version.

- **Ask about** the open project, every project, load runs only, or the last day.
- **Which endpoints does nothing test?** is answered from the catalogs, the suites and the plans together.
- **A quick model first:** it offers the smallest model you have that is not a reasoning, vision or embedding model, because on a computer without a graphics card a model that thinks before it answers can take minutes.

### Make me a plan

Ask for a load test plan and you get a plan to read, not a paragraph: every call is one the project really has, runaway numbers are brought within limits, the environment is Dispatch's own, and nothing is written until you press **Create the plan**.

### Nothing leaves the machine

Ollama on 127.0.0.1, and nothing else. The Anthropic key the assistant uses is never used here.

### What it keeps

A record of each run, plan, suite and catalog, in Dispatch's own folder on this computer. Credentials and secret values are taken out before anything is written, and **Forget everything indexed** clears the lot.

## Supported: What it reads, and what it watches

Every version below is one the integration has actually been run against; a range was run version by version, on every Java from 8 to 26 that the library itself supports. Where something is supported in the code but has not yet met a live system, the table says so.

Verified run end to end against a real service, at the version shown · Tested covered by the test suite · Recognised Instrumented supported in the code, not yet run against a live system

### Scan a project — Routes read straight from the source

**Java and Scala**

- Spring Boot — @RestController and @RequestMapping, bodies from the DTOs — Verified Spring Boot 3.3.4 · Java 21
- JAX-RS and Jakarta REST — @Path with @GET and @POST, jakarta.ws.rs or javax.ws.rs — Verified jakarta.ws.rs
- Quarkus, Micronaut — @Path, and Micronaut’s @Get and @Post — Recognised
- Play Framework — conf/routes — Verified Scala 2.13

**C#**

- ASP.NET Core controllers — [ApiController] with attribute routes — Verified .NET 8
- ASP.NET Core minimal APIs — MapGet, MapPost and the rest — Tested

**Go**

- net/http — Including Go 1.22 method patterns — Verified Go 1.23
- Gin, Chi, Gorilla mux — Tested
- Echo, Fiber — Recognised

**Python**

- FastAPI — Verified FastAPI 0.115 · Pydantic 2.9
- Django — Tested
- Flask — Recognised

### Import, send and export

**Import**

- OpenAPI — From a URL or a file — 3.0 · 3.1
- Swagger — 2.0
- Postman Collection — v2.1
- HAR — 1.2
- cURL — One command, pasted

**Send**

- HTTP, GraphQL, WebSocket, server-sent events, gRPC — GraphQL with introspection; gRPC from a .proto

**Copy as code**

- cURL, JavaScript, Python, Go, Java, C# — fetch and axios · requests · net/http · java.net.http · HttpClient

### The monitor — One agent in the JVM; web transactions from any service’s metrics

**Runtime**

- Java 8 and later — The agent is Java 8 bytecode, with no dependencies of its own — Verified JDK 8 · 11 · 17 · 21 · 26 HotSpot

**Web transactions**

- Spring Boot Actuator — Micrometer’s http.server.requests; percentiles need micrometer-registry-prometheus — Verified Spring Boot 3.3.4 · Micrometer 1.13.4
- Any service with a Prometheus request histogram — http_request_duration_seconds, as Go and Python services publish it — Tested Go 1.23 · client_golang 1.19
- OpenTelemetry HTTP metrics — http.server.request.duration — Tested

**Data stores**

- JDBC, any driver — PostgreSQL, MySQL, MariaDB, SQL Server and Oracle named from the driver — Verified H2 1.4.200 – 2.4.240 PostgreSQL 42.2.5 – 42.7.13
- HikariCP — Connection waits and pool use — Verified 3.4.5 – 7.0.2
- Redis through Lettuce — Commands, memory and hit rate; the async and reactive APIs, Jedis and Redisson not yet — Verified Lettuce 5.0.5 – 7.7.0
- MongoDB Java driver — Through the driver’s own command and pool listeners — Verified sync driver 3.12.14 – 5.11.1

**Messaging**

- RabbitMQ — amqp-client publish, Spring AMQP listeners; consuming with the plain client not yet — Verified amqp-client 4.0.3 – 5.35.0 Spring AMQP 2.2 – 4.1
- Apache Kafka — Producer sends, Spring Kafka listeners, consumer lag; a plain consumer’s poll and Kafka Streams not yet — Verified kafka-clients 2.4.1 – 4.3.1 Spring Kafka 2.5 – 4.1
- JMS and Jakarta Messaging — javax.jms and jakarta.jms; ActiveMQ, Artemis, IBM MQ, Solace and TIBCO EMS named; MessageListener and JMSContext not yet — Verified ActiveMQ 5.15 – 5.19 · 6.0 – 6.3 Artemis 2.19 – 2.57
- Amazon SQS — AWS SDK for Java 2.x, the synchronous client; the async client not yet — Verified AWS SDK 2.17 – 2.54

**Outbound HTTP**

- Spring RestTemplate — Verified Spring Framework 4.3 – 7.0
- Apache HttpClient — 4.x, and 5.x classic — Verified 4.3.6 – 4.5.14 5.0.4 – 5.6.1
- OkHttp — 3.x, 4.x and 5.x — Verified 3.12.13 – 4.12.0 5.1.0 – 5.5.0
- JDK HttpClient, HttpURLConnection, WebClient — And the async clients of OkHttp and Apache — Not yet

**Logs**

- Logback — Level, logger, thread, context and stack traces as fields — Verified 1.1.11 – 1.5.34
- Anything printing to standard output — Kept as text, the level read from the line — Tested
- Log4j2, java.util.logging — Not yet

## How it connects: The agent reports. The receiver remembers.

The agent is the only piece inside your process. It dials out — nothing in your application's network has to accept a connection — and the receiver keeps history on disk, so the screens still have yesterday in them after the service has gone.

*Diagram: The agent inside the application JVM posts reports every ten seconds to a receiver, which keeps history on disk, analyses heap dumps and serves Dispatch Studio on the desktop.*

### Credentials never leave the JVM

Flags, system properties and log-context values whose names read like credentials are masked inside the application, before anything is reported.

### Nothing to open in your network

The agent makes outbound calls only. The receiver attaches to a JVM only when you explicitly ask it to.

### Nothing leaves your machine

Your machine talks to your receiver. No account, no cloud, no telemetry. Two things send anything further, both started by you and both asking first: the assistant, and a desktop agent on a Claude model. AI Ground never does.

## APM server: For a team, a server of your own

On one developer's machine the receiver runs beside Studio. For staging and production, a team runs the APM server on its own hardware or in its own AWS account, and everyone's Studio connects to it. Nothing leaves your network.

### What it needs

Operating system · Linux, x86-64 or ARM64

Runtime · Java 21, or the container images

Up to 100 JVMs · one machine: 4 vCPU, 16 GB, 250 GB SSD

Certificate · one your JVMs already trust

### Three ways to run it

- **One machine of your own**, with Docker Compose or systemd
- **One EC2 instance** in your AWS account
- **Across availability zones on AWS**, behind a load balancer

[The setup guide, step by step](https://studio-dispatch.com/docs/apm-server.html)

## Setup: One flag, then as much or as little as you want

### Attach the agent

The agent targets Java 8 bytecode, so it attaches to anything from 8 upward — at startup, or, when the receiver is on the same machine, to a JVM that is already running, from the Live JVM screens.

```
java -javaagent:/opt/dispatch-agent.jar=\
  dispatch.apm.agent.report.url=http://127.0.0.1:8090,\
  dispatch.apm.agent.report.key=dsk_… \
  -jar your-service.jar
```

### Turn features on and off

Every setting is optional, in the agent argument, a system property, an environment variable or a properties file.

```
# /etc/dispatch-apm-agent.conf
dispatch.apm.agent.datastore.enabled=true
dispatch.apm.agent.messaging.enabled=false
dispatch.apm.agent.external.enabled=true

# the Logs screen
dispatch.apm.agent.logs.enabled=true

# leak radar
dispatch.apm.agent.radar.interval.minutes=15
```

## Pricing: Free on your machine. Per JVM on your servers.

Studio is free for one developer. When a team wants the same screens over its shared environments, it runs the APM server on its own hardware and pays per monitored JVM, however many people look.

**Studio**

Free

One developer, one machine.

- **Build**: scan a project, catalogs, environments, suites, the Fake API
- **Load**: test plans, schedules, rules after a run, PDF and Excel reports
- **The JVM monitor** for services running on your own machine, every Observe screen
- Heap dumps, thread dumps and leak tracing
- **Workflows** and **AI Ground**: a Claude model needs your own Anthropic key, a local one needs Ollama
- No account, no sign-in

**APM**

Per monitored JVM — Monthly · price announced at launch

Teams watching staging and production.

- **The APM server on your own servers**: one machine, or your AWS account
- **Everyone on the team** connects Studio to it. No per-seat price.
- Every Observe screen for every monitored JVM
- Alert rules, delivered by email and to PagerDuty
- Log capture, the leak radar, and the queries, broker calls and outbound calls behind each endpoint

**Enterprise**

Priced with you

Several teams or business units on one install.

- Everything in APM
- Separate tenants on one install Planned
- Single sign-on with SAML or OIDC Planned
- Help installing in restricted or offline networks
- Support with agreed response times

Self-hosted: your data stays in your network · No per-gigabyte charges · No per-seat charges

## Requirements: Dispatch Studio for Windows

One installer with its own runtime. It opens on a sample project, so there is something to send before you have scanned anything of your own.

Desktop · Windows 10 or 11, x64

Monitored services · Java 8 and up, HotSpot

Receiver · Java 21, on any host you choose

APM server, for teams · Linux and Java 21, or your AWS account

Local model, optional · Ollama, on the same computer

Account · None

**Dispatch Studio 0.1.41** is made by BSSR Labs.

Figures on this page were read from a running Spring Boot service at the time of writing.

© 2026 BSSR Labs
