Skip to content

Compress /solve requests#4212

Merged
squadgazzz merged 18 commits intomainfrom
gzip-solve-requests
Mar 2, 2026
Merged

Compress /solve requests#4212
squadgazzz merged 18 commits intomainfrom
gzip-solve-requests

Conversation

@squadgazzz
Copy link
Copy Markdown
Contributor

@squadgazzz squadgazzz commented Feb 25, 2026

Description

Our current /solve request can be heavy on certain chains, and given the fact that it is expected to eventually switch to a cross-chain auction, the data will be growing significantly. While it is expected to implement a delta-sync approach with event-based auction updates, this is quite involved, and as a first step, we can look into compressing the request to reduce its size and reduce network latency/delays.

The tests showed that brotli with compression level 1 outperforms gzip #4212 (comment)

Changes

##Autopilot

  • New --compress-solve-request boolean CLI flag threaded through run_loop::Config
  • solve::Request gains a compressed() method that br-compresses the body on a blocking task (CPU-intensive, like the existing serialization)
  • On compression failure, falls back to sending the uncompressed body with an error log
  • Compression time is tracked via the existing auction_overhead metric
  • Sets the Content-Encoding: br header only when the body is actually compressed
  • Add a runloop_solve_request_body_size histogram metric that records the size (in bytes) of the JSON body sent in each /solve request to drivers.

Driver

  • Adds RequestDecompressionLayer to the axum middleware stack, which automatically decompresses br-encoded request bodies based on the Content-Encoding header

How to test

New unit and e2e tests. Deploy manually with disabled compression to collect some metrics and then with compression enabled.

Related issues

Fixes #4206

@squadgazzz squadgazzz marked this pull request as ready for review February 25, 2026 19:11
@squadgazzz squadgazzz requested a review from a team as a code owner February 25, 2026 19:11
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces gzip compression for /solve requests to reduce network latency, controlled by a new --compress-solve-request flag, between the Autopilot and Driver components. A critical compilation error due to incorrect value moving in the compression logic and a high-severity issue where a metric records the compressed size instead of the uncompressed size were found.

Comment thread crates/autopilot/src/infra/solvers/dto/solve.rs Outdated
Comment thread crates/autopilot/src/run_loop.rs
@squadgazzz squadgazzz changed the base branch from solve-request-metrics to main February 25, 2026 19:21
Comment thread crates/autopilot/src/infra/solvers/dto/solve.rs Outdated
Comment thread crates/autopilot/src/infra/solvers/dto/solve.rs
Comment thread crates/e2e/tests/e2e/limit_orders.rs Outdated
Copy link
Copy Markdown
Contributor

@MartinquaXD MartinquaXD left a comment

Choose a reason for hiding this comment

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

Change looks good overall.

// axum's default body limit is 2MB too low for solvers, 20MB is still too low
// so instead of constantly guessing and updating, we disable the limit altogether
.layer(axum::extract::DefaultBodyLimit::disable())
.layer(tower_http::decompression::RequestDecompressionLayer::new())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since you had to patch the reference driver to make this work it clearly is a breaking change. But it seems like it makes sense to require every solver to support compressed requests and moving the compression flag to each solver instead of a single flag for the entire autopilot probably doesn't make sense.
I guess the gist of what I'm saying is that we need to tell solvers about this and make sure they support this before we flip the switch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm saying is that we need to tell solvers about this and make sure they support this before we flip the switch.

Yes, that is for sure.

Comment thread crates/e2e/tests/e2e/limit_orders.rs Outdated
.unwrap();
}

async fn limit_order_with_compressed_solve_request_test(web3: Web3) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't see a check actually verifying that the request was sent in a compressed way. I guess technically this test would have to have a fake driver that inspects the /solve request for the header and tries to decompress it.
As the test is right now I think we can drop it and replace it by enabling --compress-solve by default.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

True. I updated the ReverseProxy implementation and improved one of the tests. 0dc003a

Comment on lines +95 to +96
let mut encoder = GzEncoder::new(Vec::new(), Compression::new(3));
match encoder
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not suggesting to change anything in this PR just sharing some findings following @jmg-duarte's DMs about brotli compression.

on level 1 brotli is twice as fast as gzip level 3 while still beating gzip level 9 in file size. The downside is that this apparently only works over https and some solvers still use http IIRC.

brotli
Level 0:  2009237 bytes (30ms)
Level 1:  1663328 bytes (25ms)
Level 2:  1687065 bytes (44ms)
Level 3:  1647320 bytes (50ms)
Level 4:  1510469 bytes (68ms)
Level 5:  1599833 bytes (106ms)
Level 6:  1596011 bytes (129ms)
Level 7:  1592758 bytes (288ms)
Level 8:  1590406 bytes (401ms)
Level 9:  1588621 bytes (435ms)
Level 10:  1360942 bytes (3992ms)
Level 11:  1338503 bytes (11116ms)

gzip
Level 1:  2214921 bytes (67ms)
Level 2:  2179485 bytes (52ms)
Level 3:  2149025 bytes (54ms)
Level 4:  1981237 bytes (96ms)
Level 5:  1927338 bytes (118ms)
Level 6:  1883464 bytes (131ms)
Level 7:  1864462 bytes (135ms)
Level 8:  1844328 bytes (192ms)
Level 9:  1840352 bytes (255ms)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It seems like Brotli supports HTTP. Only web browsers don't support the br compression over HTTP. I can give it a try. Thanks for providing the test result!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well, after running some unit tests and adjusting the e2e test, it seems like brotli works better for sure. Switched the implementation. Thanks @jmg-duarte for the idea!

Comment thread crates/autopilot/src/infra/solvers/dto/solve.rs Outdated
@squadgazzz squadgazzz changed the title gzip /solve requests Compress /solve requests Feb 26, 2026
@squadgazzz
Copy link
Copy Markdown
Contributor Author

Ok, it seems like testing it in staging doesn't make any sense since we have very small auction jsons there. Probably, it would be better to first ask all the colocated solvers to support the br compression and then give it a try.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Feb 26, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedbrotli@​8.0.29810093100100

View full report

Copy link
Copy Markdown
Contributor

@jmg-duarte jmg-duarte left a comment

Choose a reason for hiding this comment

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

🚀

@MartinquaXD
Copy link
Copy Markdown
Contributor

MartinquaXD commented Feb 26, 2026

seems like testing it in staging doesn't make any sense since we have very small auction jsons there

If you are primarily concerned with request size you can test on shadow. Either just temporarily to not cause "down times" for solvers not supporting br or you build a custom image only sending br content to the reference drivers in our infra.
Regarding the general rollout it should be possible to just send a br encoded request to each solver URL and observe the response (e.g. status code 415 would indicate not supported). Afterwards you can reach out to all solvers that failed to test or where the results were unclear / unexpected. Note, that some solvers have firewalls only allowing requests from the autopilot IP so you might have to send the request from the autopilot pod.

If you test on shadow mainnet, please check if the times reported by the autopilot log finished streaming http request body reduce drastically. This would be a huge win and immediately unlock the hunt for 1 block per auction (as some teams reported huge variance and delays here make them nervous about reducing solve times further).

Copy link
Copy Markdown
Contributor

@MartinquaXD MartinquaXD left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for updating the tests and even switching to brotli. Very excited about the gains from this. 🤞 🚀

Comment thread crates/autopilot/src/infra/solvers/dto/solve.rs
Comment thread crates/e2e/tests/e2e/limit_orders.rs Outdated
@squadgazzz squadgazzz added this pull request to the merge queue Mar 2, 2026
Merged via the queue into main with commit 32fe75a Mar 2, 2026
20 checks passed
@squadgazzz squadgazzz deleted the gzip-solve-requests branch March 2, 2026 16:30
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 2, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore: Implement gzip compression on /solve request

4 participants