Skip to content

Offload Fastly SSAT delivery compression through EdgeZero - #884

Draft
ChristianPavilonis wants to merge 3 commits into
mainfrom
issue-858-ssat-compression-offload
Draft

ChristianPavilonis wants to merge 3 commits into
mainfrom
issue-858-ssat-compression-offload

Conversation

@ChristianPavilonis

@ChristianPavilonis ChristianPavilonis commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Offload final eligible Fastly SSAT HTML compression through EdgeZero #452. Trusted Server keeps eligibility, reader negotiation, origin decoding, HTML/EOF processing, template assembly and privacy policy.

This branch is a feature-only rebase onto current main 51730bdaf841e4d7bb96c2258e5e98169bdff9a7. It does not replay the old parser-stack or merge history. Current-main trace, ingress and absolute-deadline behavior is preserved.

Framework dependency

All six workspace EdgeZero declarations and eight lockfile packages pin exact published commit:

157f091e42b5c584898a5d0f8a0d3ddc3a4dd5ec

No registry or Fastly SDK versions changed. Both PRs stay draft for joint review. Review and merge EdgeZero first, then replace this temporary revision pin with a merged EdgeZero release before making Trusted Server merge-ready. No branch or path dependency is used.

Changes

  • Remove the application-local capability/options wrapper, opaque marker and Fastly header-finalization implementation. All four adapter app.rs files now match main.
  • Read the framework capability from the request. Keep one pending output plan that distinguishes preserved input, explicit guest encoding and adapter identity output.
  • Keep origin negotiation and decoding unchanged. Install completed identity bytes or the final identity-producing lazy stream before checked framework marking.
  • Carry the output choice through buffered/lazy delivery, template miss/hit/fallback and ordered EOF replacement/auction-tail output. Template storage remains identity and reader-neutral.
  • Call the shared Fastly finalizer after late response effects and privacy enforcement, before splitting response parts. Keep the custom streaming pump, without the framework's collecting converter.
  • Preserve deflate/failed-reader fallback, non-Fastly behavior, SSAT/consent gates, ranges, bodyless/error/unsupported responses, byte limits, auction cleanup and private/no-store rules. No publisher flag, origin-identity fetching, global compression default, retry or new limit.

Design · Implementation plan and verification record

Two consumer contract checks and a fresh independent source review found no blockers. Final runtime-input hashes matched the reviewed source.

Verification

Original integration verification at consumer db27e738 and framework 63c7b63 passed locally with Rust 1.98.1, Node 24.20.0 and Viceroy 0.21.0:

  • All 32 Rust/repository verification gates, including all adapter test/lint aliases, parity, template-build digest, WASM clock, host lint and core documentation
  • Native core: 3,345 passed, two ignored
  • Default Fastly alias: 244 adapter + 3,338 core tests passed, plus shared-crate and documentation tests
  • Reusable-sandbox Fastly alias
  • Actual Fastly deadline network cases and Cloudflare/Spin deadline runtime fixtures
  • Actual Axum and release-mode Fastly EOF controls, including disabled/success/hung lookup, auction and prefix-before-completion cases
  • JS: 1,838 passed, one skipped; formatting, type checking and build
  • Repository script/Node-pin checks, documentation formatting/lint/build, and final diff checks
  • New regression observed failing before implementation; final core matrix checks premature-intent absence, identity output and all affected delivery paths
  • Real Fastly terminal helper checks installed Once/Stream identity output after hostile late effects; genuine unmarked gzip remains unchanged

The 2026-11-03 review reruns found the SDK contract and both consumer Fastly aliases locally link-blocked on fastly_http_req::pending_req_header_insert, not just the earlier isolated-package graph. Actual hosted logs at identical reviewed source trees verify the SDK contracts, both aliases, deadline cases and release EOF controls passed in CI. Their passing hosted environment does not resolve the local discrepancy.

R1 review follow-up

Resolved local review R1 in framework 1c0f475097a813a3a9cbb7a4a121ca0523d5ed64: Vary test rows now contain literal expected header fields instead of copying the production matching predicate. No shipping SDK logic changed. Consumer 5298c0a20b664394d6ec218862296ca1ba9463b8 refreshes six declarations and eight lock sources to that exact commit, with no registry or SDK version drift.

Fresh checks passed: 13 framework native helper/core tests, SDK formatting and scoped strict Clippy; six consumer delivery tests, ten build-digest tests, consumer formatting and changed Markdown formatting. Earlier broad verification belongs to the original revisions noted above. New commits trigger fresh hosted CI.

This is not a Viceroy runtime fix. Current local loader divergence remains unresolved; no SDK stub, runtime-source/pin workaround or trap override was introduced. Real Fastly staging remains open.

CI smoke fixture fix

Framework 157f091e42b5c584898a5d0f8a0d3ddc3a4dd5ec fixes the failed reusable HTTP smoke probe. Delivery contracts had passed 12/12 and Fastly library tests 103/103; uncontrolled origin EOF could race downstream receipt.

The post-commit origin now waits for the existing client first-body-byte signal before closing short. Plain immediate aborts still serve pre-commit fault tests. Status 200, exact partial, interrupted-response type and matching guest error remain mandatory. No sleeps, retries, SDK stubs, trap overrides or runtime changes were added. Cleanup releases waiters after failed probes.

A regression failed before the fix. Final checks pass 2 core + 27 harness tests, formatting, strict Clippy and the full pinned-Viceroy Fastly smoke. All three custom variants observed the required bytes and correlated error. Two independent source investigations/reviews found no blocking issue.

Consumer 85a9b9184a67a9c827be9b59ead95a801fb07faf refreshes all six declarations/eight lock sources. Six delivery tests, ten build-digest tests and formatting pass, with no registry/SDK drift. GitHub's test workflow now passes at 157f091e, including the previously failing Fastly job. Retained CI artifacts confirm 200/partial and matching guest errors for all three custom variants. Both PRs remain draft; consumer CI runs separately.

This does not resolve the separate local debug/WASM loader discrepancy or prove live Fastly negotiation/performance.

Remaining work

  • Replace the temporary EdgeZero revision with a merged release before merge-ready.
  • Verify real Fastly reader negotiation, including absent/identity-only/identity-refusing preferences, final encoding and decoded HTML equivalence.
  • Verify progressive CDN delivery and service-chain behavior.
  • Collect fresh inline/template-miss/template-hit vCPU, TTFB, origin-byte and browser-byte measurements.

No deployment, merge or readiness change ran. Local/Viceroy evidence proves guest behavior, not CDN compression or performance. Historical July measurements are background only.

Closes #858. Framework tracking: EdgeZero #362.

@ChristianPavilonis

Copy link
Copy Markdown
Collaborator Author

Remove the opt in

@aram356
aram356 marked this pull request as draft July 27, 2026 16:26

@prk-Jr prk-Jr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean, well-gated rollout flag. The three-way gate (setting + adapter capability + existing SSAT eligibility), the explicit DeliveryCompressionCapability declaration at each adapter boundary, and the forward-compatible config serialization are all the right shape, and the test coverage on the new paths is genuinely good. One question about the PR description's stated behavior/measurement, plus a few non-blocking notes.

Blocking

❓ question

  • PR description and measurement no longer describe the shipped behavior: The description says "request identity HTML from the origin" and "Trusted Server sends Accept-Encoding: identity to the publisher origin". The code does not do this — restrict_accept_encoding is unchanged, and the new tests assert gzip, br is still forwarded to the origin (crates/trusted-server-core/src/publisher.rs:534, :620, :756). docs/guide/configuration.md describes the actual behavior correctly ("continues to negotiate only supported encodings with the publisher origin"), so only the PR body is stale — presumably from before "Fix SSAT compression offload rollout safety".

    Two consequences worth confirming before merge:

    1. The staging measurement (guest 44.6 ms → 9.0 ms, vCPU 47 ms → 19 ms) was taken with identity origin responses. What ships still decodes gzip/deflate/br in the guest and only drops the re-encode. The re-encode is likely the dominant cost, so most of the win probably survives — but the number in the description does not describe this build. Has it been re-measured with negotiated origin responses?
    2. The stated tradeoff ("identity origin responses are substantially larger and still count against the current Fastly 10 MiB raw origin-response limit") no longer applies, since origin responses stay compressed. The remaining size pressure moved to the in-guest buffer instead — see the max_buffered_body_bytes note below.

Non-blocking

🤔 thinking

  • Offload shifts max_buffered_body_bytes from bounding compressed output to bounding uncompressed output (crates/trusted-server-core/src/publisher.rs:2405)
  • No coverage for the HTML post-processor buffered path under offload (crates/trusted-server-core/src/publisher.rs:915)

🌱 seedling

  • Delivery capability is a per-call-site literal (crates/trusted-server-adapter-fastly/src/app.rs:801)

📌 out of scope

  • New env-override block documents a mechanism that is test-only at runtime (docs/guide/configuration.md:342)

👍 praise

  • Capability decoupled from EdgeCacheHeader (crates/trusted-server-core/src/publisher.rs:1885)
  • Forward-compatible config serialization with a test and a documented rollback order (crates/trusted-server-core/src/settings.rs:56)
  • Fastly delivery billing warning in the docs — uncompressed-size billing is exactly the kind of thing that gets discovered after rollout, not before.

CI Status

test.yml and format.yml trigger only on pull requests to main or feature/**, so this PR (base refactor/ssat-streaming) ran only the four integration-test checks — all passing. The fmt/clippy/unit-test gates were run locally at 68c67c9:

  • fmt: PASS (cargo fmt --all -- --check)
  • clippy: PASS (clippy-fastly, clippy-axum, clippy-cloudflare, clippy-cloudflare-wasm, clippy-spin-native, clippy-spin-wasm)
  • rust tests: PASS (core 1660 under Viceroy; axum, cloudflare, spin adapters)
  • GitHub integration tests: PASS (4/4)

Comment thread docs/guide/configuration.md Resolved
@ChristianPavilonis ChristianPavilonis changed the title Add opt-in SSAT compression offload Offload Fastly SSAT delivery compression Oct 29, 2026
@ChristianPavilonis
ChristianPavilonis changed the base branch from refactor/ssat-streaming to main October 29, 2026 18:04
Consume the exact framework PR revision while both PRs remain draft. Keep eligibility and output planning in publisher code and apply shared Fastly finalization after late effects.
@ChristianPavilonis
ChristianPavilonis force-pushed the issue-858-ssat-compression-offload branch from 5b663ee to db27e73 Compare November 2, 2026 21:32
@ChristianPavilonis ChristianPavilonis changed the title Offload Fastly SSAT delivery compression Offload Fastly SSAT delivery compression through EdgeZero Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Offload Fastly SSAT delivery compression from the Compute guest

2 participants