Goblin - Chaos Engineering Extension for Quarkus

Goblin is a chaos engineering extension for Quarkus that lets you inject latency, exceptions, HTTP failures, and dependency degradation into your running application — without touching a single line of source code.

It is designed for one specific purpose: verifying that your resilience mechanisms actually work. You declared @Timeout, @Fallback, @Retry, health probes, or circuit breakers? Goblin gives you the tool to prove they hold under real failure conditions — at the HTTP boundary, on outgoing HTTP calls, and directly inside your business beans through a service-layer interceptor that runs with Fault Tolerance.

Think of Goblin as Chaos Monkey for the Quarkus ecosystem — but with stronger safety guarantees.

Why Goblin?

Quarkus has excellent resilience primitives (MicroProfile Fault Tolerance, Mutiny reactive timeouts, health probes), but no built-in way to trigger the failures these mechanisms are supposed to handle. You end up writing fragile integration tests that mock exceptions, or worse, discovering production failure modes for the first time in production.

Goblin fills that gap: inject realistic failures at the HTTP layer during development, observe how your application reacts, and iterate.

Key design decisions:

  • Dev by default, tests on opt-in. Chaos activates under quarkus:dev, and under @QuarkusTest only with quarkus.goblin.test.enabled=true, so adding the extension never slows down nor breaks an existing test suite. In a production build the engine stays inactive whatever the configuration, the Dev UI is absent, and no application bean is woven with the service-assault interceptor; only the (inert) runtime classes ship in the extension jar.

  • Zero code modification. No @ChaosLatency annotations to scatter across your endpoints. Configuration is the only interface.

  • Non-destructive. You can target specific packages, exclude annotated methods, and control the percentage of affected requests.

  • Composable. Multiple assault types can be active simultaneously on the same request.

  • Multi-layer. Chaos resolves per request (or per consumed message) against the armed layers (DATABASE → MESSAGING → SERVICE → HTTP_IN, with HTTP_OUT rolled per outgoing call), so a fault injected deepest propagates up through the resilience mechanisms above it.

  • Persistent state. Dev UI config changes survive restarts via automatic disk persistence (.goblin-state.json).

  • Repeatable experiments. Save the current assault configuration as a named scenario and rerun it in one click, from the Dev UI or through Dev MCP (.goblin/scenarios/).

Quick start

Add the dependency

<dependency>
    <groupId>io.quarkiverse.goblin</groupId>
    <artifactId>quarkus-goblin</artifactId>
    <version>${goblin.version}</version>
</dependency>

That’s it. Start your application in dev mode:

./mvnw quarkus:dev

You will see a warning log confirming chaos is active:

WARN  Chaos engineering active: 100% of REST requests subject to assault (profile=NONE, latency=true, exception=false, httpStatus=false, dependencyDegradation=false, clientLatency=false, clientException=false, responseBody=false)

Verify it works

With the default configuration (latency assault enabled, 100% of requests), every REST endpoint will have an artificial delay applied. Hit any endpoint and observe the added latency:

curl -w "\nTime: %{time_total}s\n" http://localhost:8080/api/hello

You should see a response time well above your normal baseline.

Explore the documentation

  • Assault types — the six server-side chaos assaults (latency, exception, HTTP status, dependency degradation, response body, response header), service-layer assaults on business beans, plus client-side assaults for outgoing REST Client and Vert.x WebClient calls.

  • Profiles — bundle common effects into SLOW_FAILURE, INTERMITTENT or TIMEOUT.

  • Targeting — blast radius, package and annotation filters.

  • Configuration reference — every configuration key and the startup/Dev UI validation rules.

  • Dev UI panel — the Chaos Dashboard, the Assault History panel, and the Markdown report export.

  • How it works — JAX-RS filter mechanics, runtime config modification, state persistence, and adding your own assault type.

  • Metrics (Micrometer / Prometheus) — optional Micrometer / Prometheus metrics for assault activity (quarkus-goblin-metrics).

  • Tracing (OpenTelemetry) — optional OpenTelemetry spans for each assault (quarkus-goblin-opentelemetry).

  • Compatibility — coexistence with MicroProfile Fault Tolerance (service-layer interceptor placement), Quarkus REST, the REST clients and the optional database and messaging hooks.

  • Troubleshooting — common issues and their fixes.

  • End-to-end example: prove your resilience annotations work — prove that your @Timeout and @Fallback actually work.

  • JSON-RPC reference — the JSON-RPC API used by the Dev UI, for scripting and CI validation.

FAQ

Does Goblin run in production?

No. The chaos implementation is only activated in dev mode and, on opt-in, in test mode. The runtime ships in quarkus-goblin, while the Dev UI components live in the runtime-dev module (quarkus-goblin-dev), which is only attached in dev mode.

Do I need to annotate my endpoints?

No. Goblin intercepts at the JAX-RS filter level automatically. The only interface is configuration, either static (application.properties) or dynamic (Dev UI / JSON-RPC).

What is the maximum assault history size?

The history buffer is capped at the latest 1000 entries; the oldest are dropped automatically.

Can I combine latency and exception to simulate a slow failure?

Yes. Multiple assault types can be active on the same request. In that case the latency (delay) is applied first, then the exception is thrown — ideal for verifying that @Timeout triggers before @Fallback, or that a fallback handles an exception raised after a slow response.

What happens if my exception class cannot be constructed?

If the configured class does not exist or has no String constructor, Goblin falls back to a RuntimeException carrying the configured message. See the Troubleshooting page.

Are Dev UI changes persisted?

Yes. Runtime changes are automatically saved to a .goblin-state.json file in the project working directory and restored on the next startup. Add .goblin-state.json to your .gitignore: it holds your local chaos settings, and a committed copy would silently replace the application.properties configuration of your teammates in dev mode.

Non-goals

  • Infrastructure chaos (pod killing, network partitioning) — use Chaos Mesh, Litmus, or Pumba for that.

  • Production or staging chaos — Goblin is a dev-mode tool. Chaos belongs in the hands of someone who is watching the application, with an auto-off set.

  • CI pipelines — no scenario files run non-interactively. A pipeline runs where nobody is watching; saved scenarios exist to replay an experiment by hand.

  • A rules engine — no declarative expectations evaluated into pass/fail. Goblin provides the signals (history, counters, metrics, spans); the agent or the human concludes.

  • Running in native mode — the extension must not break a native build when it sits in the dependencies, nothing more.

Requirements

  • Java 25 or later

  • Quarkus 3.38.3 or later