skip to content

threaddump, heapdump & httpexchanges

Thread dumps, heap dumps and recent HTTP exchanges are available over HTTP for live diagnosis. Interviewers pair the usefulness with the risk: a heap dump endpoint is an exfiltration channel if it is exposed.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

Why does /actuator/httpexchanges return nothing (or 404) even after you expose it, and how do you make it work?

level: middleimportance: must knowfreq 50%

answer

  1. @ConditionalOnBean(HttpExchangeRepository)
  2. no repository auto-configured since 3.0/2.2
  3. declare InMemoryHttpExchangeRepository bean
  4. ring buffer default 100, volatile
  5. was httptrace in Boot 2.x

basics

~10 s

Spring Boot doesn't auto-create the storage for it. You must define an HttpExchangeRepository bean — usually InMemoryHttpExchangeRepository — so exchanges are recorded. Without that bean the endpoint isn't registered even if you exposed it.

solid answer

~40 s

The httpexchanges endpoint only records and shows data if an HttpExchangeRepository bean exists in the context. Since Spring Boot 3.0 (and effectively 2.2) no such bean is auto-configured, so the HttpExchangesEndpoint is @ConditionalOnBean and simply isn't created — you get a 404 or empty results despite adding it to management.endpoints.web.exposure.include. The fix is to declare a bean, typically new InMemoryHttpExchangeRepository(), which keeps the last 100 exchanges in a ring buffer (configurable via setCapacity). This replaced the Boot 2.x httptrace endpoint and its HttpTraceRepository. Because the in-memory store is bounded and lost on restart, it's a live-debugging aid, not an audit log. You control captured fields with management.httpexchanges.recording.include (headers, principal, remote address) and can pause capture with recording.enabled=false.

code

java · 15 lines
java
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ActuatorConfig {

    @Bean
    HttpExchangeRepository httpExchangeRepository() {
        InMemoryHttpExchangeRepository repo = new InMemoryHttpExchangeRepository();
        repo.setCapacity(200); // default is 100
        return repo;
    }
}

go deeper

for a junior

Know the endpoint needs a repository bean to work.

for a middle

Name InMemoryHttpExchangeRepository, its default capacity, and the @ConditionalOnBean wiring.

for a senior

Explain the httptrace→httpexchanges rename and recording.include tuning, plus privacy tradeoffs.

for a principal

Argue for observability/tracing over this endpoint in production and reason about a custom durable repository's cost/PII risk.

**The gotcha.** Developers expose `httpexchanges`, hit `/actuator/httpexchanges`, and see either a 404 or an empty `{"exchanges":[]}` that never fills. The reason: the endpoint needs somewhere to store exchanges, and Spring Boot **does not auto-configure that storage**. **Mechanism.** The endpoint bean `HttpExchangesEndpoint` is registered by `HttpExchangesEndpointAutoConfiguration` under `@ConditionalOnBean(HttpExchangeRepository.class)`. The repository is the `HttpExchangeRepository` interface. Spring Boot ships an implementation — `InMemoryHttpExchangeRepository` — but **does not create it for you** (this was deliberately removed to avoid an unbounded/unexpected in-memory buffer and privacy surprises). So if no `HttpExchangeRepository` bean exists, the endpoint is never created, and exposure config has nothing to expose → 404. If you define the bean but the endpoint isn't exposed, you get 404 for a different reason. You need **both**: the bean *and* web exposure. **The fix.** Declare a bean: ```java @Bean HttpExchangeRepository httpExchangeRepository() { return new InMemoryHttpExchangeRepository(); } ``` `InMemoryHttpExchangeRepository` is a fixed-capacity ring buffer (default **100**), newest-first; call `setCapacity(int)` to change it. It only records HTTP **server** exchanges, and the data is **volatile** — gone on restart and evicted once capacity is exceeded. **Recording it captures.** Spring wires an `HttpExchangesFilter` (a servlet filter) that writes each completed exchange into the repository. Configure the captured detail with: - `management.httpexchanges.recording.enabled` (default true) — master on/off. - `management.httpexchanges.recording.include` — a set from `Include`: `REQUEST_HEADERS`, `RESPONSE_HEADERS`, `COOKIE_HEADERS`, `AUTHORIZATION_HEADER`, `PRINCIPAL`, `REMOTE_ADDRESS`, `SESSION_ID`, `TIME_TAKEN`. Sensitive headers like Cookie/Authorization are excluded by default. **Naming history.** In Boot 2.x this was the **`httptrace`** endpoint with `HttpTraceRepository` / `InMemoryHttpTraceRepository`. Boot 3.0 renamed everything to `httpexchanges` / `HttpExchangeRepository` / `InMemoryHttpExchangeRepository`. Old configuration property `management.trace.http.*` became `management.httpexchanges.recording.*`. **When to use.** Great for quick local/dev inspection of recent traffic. In production prefer proper observability — Micrometer `Observation`/tracing, access logs, or an APM — because the in-memory buffer is tiny, non-persistent, and holds request data (potential PII) in memory. If you need durable history, implement `HttpExchangeRepository` over a datastore, but weigh privacy and volume first.

  • What was this endpoint called in Spring Boot 2.x, and what changed in 3.0?
    It was 'httptrace' backed by HttpTraceRepository/InMemoryHttpTraceRepository. Boot 3.0 renamed it to 'httpexchanges' with HttpExchangeRepository/InMemoryHttpExchangeRepository, and properties moved from management.trace.http.* to management.httpexchanges.recording.*.
  • Why is the in-memory repository not a good production audit trail?
    It's a small bounded ring buffer (default 100 exchanges), stored only in heap, so it's lost on restart, evicts old entries quickly, doesn't span multiple instances, and can hold PII in memory. Use durable logging/APM/tracing instead.
  • Are cookie and authorization headers recorded by default?
    No. Sensitive headers are excluded by default; you'd have to opt in via management.httpexchanges.recording.include (COOKIE_HEADERS, AUTHORIZATION_HEADER), which is usually a bad idea for security.

saying these in an interview costs you the question

  • Claiming Spring Boot auto-creates an in-memory repository for httpexchanges
  • Thinking exposure alone (exposure.include) makes the endpoint work
  • Treating httpexchanges as a durable/audit log
  • Confusing it with distributed tracing / Micrometer tracing

context

open as a page

What are the /actuator/threaddump, /actuator/heapdump and /actuator/httpexchanges endpoints, and what does each return?

level: juniorimportance: should knowfreq 55%

basics

~10 s

They are Spring Boot Actuator diagnostic endpoints. threaddump returns a snapshot of all JVM threads and their states, heapdump downloads a binary .hprof memory-dump file, and httpexchanges shows the most recent HTTP request/response exchanges.

open as a page

What exactly does GET /actuator/heapdump produce, and what operational cautions apply when triggering it?

level: seniorimportance: should knowfreq 42%

basics

~20 s

It generates and downloads a binary HPROF (.hprof) heap dump of the live JVM heap via the HotSpotDiagnosticMXBean. It's large (roughly heap size), pauses the app while dumping, and contains all in-memory data including secrets.

open as a page

How do you use /actuator/threaddump to diagnose a hang or deadlock — what fields matter and what do thread states tell you?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The thread dump lists every thread with its state and stack trace. Many threads BLOCKED on the same lock, or two threads each holding a lock the other wants, points to contention or a deadlock. RUNNABLE threads stuck in the same frame suggest a hot loop.

open as a page

How would you safely expose these diagnostic endpoints in production, given heapdump/threaddump can leak sensitive data?

level: principalimportance: should knowfreq 35%

basics

~10 s

Don't expose them publicly. Keep only health public, put diagnostic endpoints behind authentication/authorization, ideally on a separate internal management port, and restrict access to operators. Treat any heap dump as a secret.

open as a page