Files

4.6 KiB

Web Advanced: support matrix

Every capability is off unless named. WebAdvancedPromotionGate.forFeature is the machine-checked form of the last two columns; if this table disagrees with it, the code wins.

Capability Flag What it adds Required suites Soak
MVC_VIRTUAL_THREADS backend.web.advanced.mvc-virtual-threads.enabled A different scheduling model for every request web:test, webCrossStackParityTest, virtual-thread-admission, pinning-jfr 24h
WEBFLUX_BLOCKING_BRIDGE …webflux-blocking-bridge.enabled A bounded offload; affects the shared event loop web:test, blocking-bridge-bounded, event-loop-guard 24h
JSON_MERGE_PATCH …json-merge-patch.enabled RFC 7396, partial documents web:test, patch-security, patch-atomicity 8h
JSON_PATCH …json-patch.enabled RFC 6902, arbitrary pointers as merge patch 8h
SSE …sse.enabled Long-lived connections web:test, streaming-soak-10k, slow-consumer-bounded, cancellation-propagation, pod-drain 24h
NDJSON …ndjson.enabled Long-lived connections as SSE 24h
JSON_SEQUENCE …json-sequence.enabled Long-lived connections as SSE 24h
FUNCTIONAL_WEBFLUX …functional-webflux.enabled Routes with no annotation to scan web:test, functional-route-parity 8h
CBOR …cbor.enabled A second decoder web:test, codec-security, codec-budget 8h
XML …xml.enabled A decoder with dangerous defaults as CBOR 8h
OPENAPI_32 …openapi-32.enabled A parallel description artifact web:test, openapi-32-toolchain-matrix 8h
RATELIMIT_DRAFT_HEADERS …ratelimit-draft-headers.enabled Additive response headers web:test, ratelimit-draft-headers 8h

Two capabilities change requests that do not use them

WebAdvancedFeature.affectsUnrelatedRequests() is true for exactly MVC_VIRTUAL_THREADS and WEBFLUX_BLOCKING_BRIDGE. A codec affects only requests that negotiate it; a virtual-thread executor affects every request in the process, and the blocking bridge affects the event loop they all share. WebAdvancedFeatureFlags.stableBehaviourPreserved() reports whether either is on.

That distinction is why those two soak for 24 hours and why their rollback test is the one that matters most.

What is refused, and why the row is here

Refused Reason
Virtual threads without an admission limit The pool size was the admission policy. Removing it accepts every arrival and queues them on downstream budgets that did not grow.
A blocking offload for an unregistered operation boundedElastic() is reachable from anywhere and unbounded in practice; an unenumerable set of offloads is invisible until the pool is the heap.
A merge patch outside its field allowlist A merge patch is partial, so no DTO's absent fields say "not permitted". Without an allowlist the writable set grows every time somebody adds a field.
A JSON Patch pointer above its allowed prefix Replacing a parent deletes every sibling, so permission on a child cannot grant it.
A move whose source is unauthorized Checking only the destination lets a caller relocate data out of a field they may not touch.
XML with a DTD or an external entity Billion-laughs and XXE. Neither errors when it fires; the parse succeeds and the document contains something it should not.
A non-JSON representation without all three gates Flag, route produces, and client allowlist. An Accept header is not evidence the route was tested against that codec.
Compression-style silent fallback on a 406 A client that asked only for CBOR and gets JSON parses the bytes as CBOR and fails somewhere far away.
Changing HTTP status after commit The body becomes half stream, half JSON, and the 200 is cached.
Unbounded buffering for a slow consumer It moves the client's slowness into the server's heap.

Promotion

Each capability is promoted on its own evidence. Two conditions apply to all and are not waivable:

  • Rollback exercised. A flag nobody has turned off is not known to turn off.
  • Stable behaviour unchanged with the feature off. If it is not, the feature was never optional and every deployment has it.

Parsers and patch appliers additionally require a security review — WebAdvancedPromotionGate.needsSecurityReview names them.

See docs/adr/ADR-WEB-ADV-001-streaming-is-live-delivery.md, ADR-WEB-ADV-002-virtual-threads-do-not-remove-admission.md, and ADR-WEB-ADV-003-openapi-32-remains-experimental.md.