ADR 0008.1: Browser Backend Evaluation & Selection (Phase 5.1)¶
Status¶
Implemented (v0.0.5)
Context¶
As part of the v0.0.5 initiative, we replaced the Node.js/Playwright dependency with a Rust-native solution for diagram rendering (Mermaid, BPMN).
Performance and stability benchmarks were conducted in a standalone experiment (experiments/browser-eval).
Capability Testing Methodology¶
The following capabilities were tested to verify production readiness:
Cold-Start Launch: Measuring the time from process start to a responsive DevTools Protocol (CDP) session.
Secure Navigation: Verifying HTTPS handshaking and certificate handling during page load.
Headless Detection Bypass: Ensuring the browser instance can render complex JavaScript (Mermaid.js) without being blocked by basic headless detection scripts.
Synchronous vs. Async Threading: Testing how the library handles long-running renders within a shared thread pool (merging the “Playwright Pooling” concept from ADR 0004).
Memory Pressure/Dangling Resources: Verifying that closing the high-level
Browserobject correctly terminates underlyingchromechild processes.Error Propagation: Capturing and normalizing CDP-level errors (e.g., TargetClosed, NavigationTimeout) into meaningful Rust
Resulttypes.
Evaluation Results¶
| Metric | headless_chrome | chromiumoxide | fantoccini |
|---|---|---|---|
| Total Duration | 3.9s | FAILED (1.2s + error) | N/A (Note 1) |
| Launch Time | 402ms | 1.2s | N/A |
| Binary Size (Delta) | +9.3 MB | +6.9 MB | +28 KB (Note 2) |
| API Complexity | Low (Sync/Native) | High (Async Stream) | Medium |
| External Deps | System Chrome | System Chrome | Chrome + Driver |
| Stability | High | Low (Async drift) | High |
Note 1:
fantoccinirequires a standalonechromedriverprocess, which contradicts our goal of reducing external runtime dependencies and binary footprint. Note 2: Whilefantoccini’s direct binary footprint is negligible (+28 KB), the requiredchromedriverbinary adds ~15-20 MB of hidden external dependency weight.
Decision¶
We adopted headless_chrome as the primary browser backend for kroki-rs.
Rationale¶
Performance:
headless_chromedemonstrated a extremely fast cold-start and navigation cycle (under 4s for a full external page load and screenshot).Simplicity: The synchronous API of
headless_chromesimplifies local thread management and pooling without the “oneshot canceled” hazards observed inchromiumoxide’s async handler lifecycle.Deployment: It works directly with any installed Google Chrome, Chromium, or Brave binary, matching the current user-level requirements while eliminating Node.js.
Consequences¶
The
BrowserBackendtrait in v0.0.5 will be modeled aroundheadless_chromecapabilities.We will implement a connection-pooling strategy (similar to ADR 0004) to further reduce the 400ms launch latency for sub-sequential requests.
Node.js and Playwright will be removed from the CI and build pipelines once the migration is complete.