ASP.NET Core  

Benchmarking .NET 11 HTTP Compression for Large JSON APIs

Large JSON responses are common in modern APIs. Reporting endpoints, search APIs, analytics dashboards, catalog services, and data-export APIs can easily return hundreds of kilobytes or several megabytes of JSON.

Without compression, the response size can become a significant part of the application's network cost and latency.

A simplified request looks like this:

Client
   |
   | HTTP Request
   v
ASP.NET Core API
   |
   v
JSON Serialization
   |
   v
Large JSON Payload
   |
   v
Network
   |
   v
Client

With HTTP compression:

Client
   |
   | Accept-Encoding: gzip, br, zstd
   v
ASP.NET Core API
   |
   v
JSON Serialization
   |
   v
Compression
   |
   v
Smaller Payload
   |
   v
Network
   |
   v
Client Decompression

Compression can significantly reduce bytes transferred, but it is not free. The server must spend CPU time compressing the response, while the client must decompress it.

That creates an important engineering question:

At what payload size does HTTP compression provide a meaningful benefit, and which compression algorithm offers the best trade-off between size, CPU usage, and latency?

This article presents a practical benchmarking approach for large JSON APIs in .NET 11, focusing on response size, compression ratio, CPU overhead, latency, throughput, and concurrency.

Introduction

JSON is convenient because it is readable, interoperable, and supported by virtually every modern application platform.

It is not, however, particularly compact.

Consider a response containing thousands of records:

{
  "items": [
    {
      "id": 1001,
      "name": "Enterprise Product",
      "description": "A detailed product description...",
      "category": "Software",
      "status": "Active"
    }
  ]
}

JSON contains repeated property names and textual values.

Compression algorithms can take advantage of that repetition.

For example:

Uncompressed
     |
     | 1.8 MB
     v
Compression
     |
     | 240 KB
     v
Network

The actual result depends heavily on the structure and entropy of the payload.

A useful benchmark therefore needs to measure more than whether compression is enabled.

Why Benchmark HTTP Compression?

Compression affects several parts of API performance.

Network Transfer

Smaller responses require fewer bytes to transfer.

Response Latency

On bandwidth-constrained networks, fewer bytes can reduce transfer time.

CPU Usage

Compression consumes server CPU.

Throughput

Higher CPU usage can reduce the number of requests a server can process concurrently.

Memory

Compression buffers and serialization can influence memory usage.

The objective is not:

"Maximum compression"

The objective is:

Best Overall Trade-off
=
Payload Reduction
+
Latency
+
CPU
+
Throughput

Compression Algorithms

Common HTTP content-encoding options include:

AlgorithmTypical Characteristics
GzipBroad compatibility and mature implementation
BrotliOften strong compression for text-based payloads
ZstandardDesigned for strong compression with good performance
IdentityNo compression

The exact availability and behavior depend on the .NET and ASP.NET Core version, server configuration, and client capabilities.

Do not assume that one algorithm is universally faster or smaller. Benchmark it with the payloads your application actually serves.

ASP.NET Core Response Compression

ASP.NET Core provides response compression middleware.

A basic configuration looks like:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
});

var app = builder.Build();

app.UseResponseCompression();

app.MapGet("/api/products", () =>
{
    return Results.Ok(CreateProducts());
});

app.Run();

The middleware examines the request's Accept-Encoding header and determines whether an appropriate response encoding can be used.

For example:

GET /api/products HTTP/1.1
Accept-Encoding: br, gzip

The server can then return a compressed representation when the response is eligible.

Important: Compression Is Not the Same as Serialization

This distinction matters when benchmarking.

The API pipeline generally performs:

Object
  |
  v
JSON Serialization
  |
  v
JSON Bytes
  |
  v
Compression
  |
  v
HTTP Response

Compression cannot make serialization itself faster.

If JSON serialization takes 30 ms and compression takes 10 ms:

Total server processing
≈ 40 ms

Changing the compression algorithm does not eliminate the serialization cost.

Therefore, benchmark these stages separately when possible.

Create a Representative Large JSON Payload

A benchmark should use realistic data.

For example:

public sealed record Product(
    int Id,
    string Name,
    string Category,
    string Description,
    decimal Price,
    bool IsActive);

Generate thousands of records:

static IReadOnlyList<Product> CreateProducts(int count)
{
    return Enumerable.Range(1, count)
        .Select(i => new Product(
            i,
            $"Product {i}",
            i % 2 == 0 ? "Software" : "Hardware",
            "Enterprise product description with repeated text " +
            "that represents a realistic API payload.",
            100 + i,
            true))
        .ToArray();
}

The benchmark should use the same dataset for every compression configuration.

Test Multiple Payload Sizes

Do not benchmark only one response size.

A useful test matrix is:

10 KB
50 KB
100 KB
250 KB
500 KB
1 MB
5 MB
10 MB

The goal is to identify the point at which compression becomes worthwhile.

For very small responses, compression may provide little benefit because the compressed representation can still have protocol and CPU overhead.

For large repetitive JSON payloads, compression can produce a much larger reduction in transferred bytes.

Establish a Baseline

Always benchmark an uncompressed response.

Scenario A
Compression disabled

Then compare:

Scenario B
Gzip

Scenario C
Brotli

Scenario D
Zstandard, where supported and configured

The baseline gives you the reference point.

Without it, a compression benchmark cannot answer whether compression actually improved the API.

Measure Response Size

The first metric is compressed size.

For example:

Uncompressed: 2,400 KB
Compressed:     310 KB

Compression ratio:

310 / 2400 = 12.9%

Payload reduction:

1 - (310 / 2400)
= 87.1%

Track both values.

Compression ratio tells you how much of the original payload remains.

Payload reduction is often easier to communicate to engineering and product teams.

Measure Latency

Measure at least:

  • Mean latency

  • Median latency

  • p95 latency

  • p99 latency

Averages alone can hide tail behavior.

For example:

Configurationp50p95p99
No compression70 ms110 ms180 ms
Gzip58 ms95 ms150 ms
Brotli55 ms90 ms145 ms

These values are illustrative. Your benchmark must use actual measurements from your environment.

Why Compression Can Reduce Latency

At first this seems counterintuitive.

Compression adds CPU work, so why can it make an API faster?

Because the network may be the dominant cost.

Consider:

Uncompressed:
CPU: 20 ms
Network: 180 ms
Total: 200 ms

Compressed:

CPU: 30 ms
Network: 60 ms
Total: 90 ms

Compression added 10 ms of CPU work but removed 120 ms of network transfer.

The opposite can happen on a fast local network:

Uncompressed:
CPU: 20 ms
Network: 10 ms
Total: 30 ms

Compressed:
CPU: 35 ms
Network: 4 ms
Total: 39 ms

This is why benchmark environment matters.

Measure CPU Usage

Compression can become expensive under high concurrency.

Suppose:

100 requests/sec

and each request produces a 5 MB response.

The server may spend substantial CPU time serializing and compressing those responses.

Track:

CPU utilization
CPU time per request
Requests/sec
p95 latency

Compare compressed and uncompressed scenarios at the same concurrency.

Measure Throughput

A useful benchmark question is:

How many large JSON responses can the server deliver per second?

Run the same workload under different configurations.

For example:

Concurrency: 1
Concurrency: 10
Concurrency: 50
Concurrency: 100

Then measure:

Requests/sec
CPU
Memory
p95 latency
Payload bytes/sec

This reveals whether compression improves network efficiency at the expense of server capacity.

Use a Proper Benchmark Harness

For HTTP benchmarking, use a dedicated load-testing or benchmarking tool rather than timing a single request manually.

A typical workload should define:

Target endpoint
Payload size
Compression setting
Client Accept-Encoding
Concurrency
Duration
Warm-up
Connection behavior

Keep all other variables constant.

Control the Client

Compression is negotiated through request headers.

For example:

Accept-Encoding: gzip

or:

Accept-Encoding: br

or:

Accept-Encoding: zstd

depending on client and server support.

A fair benchmark must make sure the client actually requests the encoding being tested.

Otherwise, you may believe you are benchmarking Brotli while the response is actually uncompressed.

Inspect the Response Headers

Always verify:

Content-Encoding: br

or:

Content-Encoding: gzip

and compare:

Content-Length

when available.

For dynamically generated responses, transfer behavior may involve chunking or HTTP/2/HTTP/3 framing, so application-level measurements should not rely exclusively on Content-Length.

Test HTTPS

Do not benchmark only HTTP.

Production APIs commonly use HTTPS.

Compression behavior can interact with:

  • TLS

  • HTTP/2

  • HTTP/3

  • connection reuse

  • proxy infrastructure

  • reverse proxies

Enable the same transport configuration used by production.

HTTP/2 and HTTP/3

Modern APIs frequently operate over HTTP/2 or HTTP/3.

Your benchmark should therefore compare realistic production transport conditions.

A useful matrix might be:

HTTP/1.1 + Compression
HTTP/2  + Compression
HTTP/3  + Compression

The goal is not necessarily to compare protocols in isolation, but to understand whether the compression strategy behaves differently under the application's actual transport.

Benchmark Repeated Data vs High-Entropy Data

JSON payload structure has a major impact on compression.

Compare:

Highly Repetitive Payload

Product
Product
Product
Product
Product

with repeated field names and similar descriptions.

High-Entropy Payload

Random identifiers
Unique strings
Encoded values
Different descriptions

Compression generally benefits more from repeated patterns.

Therefore, a benchmark using artificially repetitive JSON can exaggerate compression effectiveness.

Test Realistic Enterprise Data

A good benchmark dataset should contain:

  • Repeated property names

  • Variable strings

  • Numeric values

  • Dates

  • IDs

  • Nested objects

  • Arrays

  • Optional properties

  • Realistic text lengths

For example:

{
  "orderId": "ORD-98231",
  "customer": {
    "id": "CUS-19382",
    "name": "Example Customer"
  },
  "items": [
    {
      "sku": "SKU-1021",
      "quantity": 4,
      "price": 125.50
    }
  ]
}

This provides a better approximation of production JSON.

Benchmark Nested JSON

Large enterprise responses often contain nested structures.

Response
 |
 +-- Customer
 |
 +-- Orders
 |     |
 |     +-- Items
 |
 +-- Payments
 |
 +-- Shipping

Measure compression with different nesting depths.

Nested structures can affect both serialized size and compression efficiency.

Test Streaming Responses Separately

A large JSON array generated as one response is different from a streaming response.

For example:

Serialize Entire Object
       |
       v
Compress
       |
       v
Send

versus:

Generate Item
    |
    v
Serialize
    |
    v
Compress
    |
    v
Send
    |
    v
Next Item

Streaming can improve time-to-first-byte and memory behavior, but the interaction with compression needs to be measured independently.

Do not combine streaming and compression into a single benchmark conclusion without identifying which behavior produced the improvement.

Benchmark Cold and Warm Runs

JIT compilation, connection establishment, caches, and other initialization work can distort results.

Use:

Warm-up
   |
   v
Measurement
   |
   v
Multiple Iterations

Do not include startup costs in every measurement unless startup performance is specifically what you are testing.

Test Compression Levels

Some compression implementations expose configurable compression levels.

Conceptually:

Fast
Balanced
Smallest

Higher compression levels may reduce payload size but consume more CPU.

Benchmark each relevant level.

The important metric is not simply:

Smallest payload wins

but:

Total Cost
=
CPU
+
Network
+
Latency
+
Infrastructure

A Simple Compression Benchmark

For algorithm-level experiments, you can benchmark compression independently of HTTP.

static byte[] Compress(
    byte[] data,
    Stream compressor)
{
    compressor.Write(data, 0, data.Length);
    compressor.Flush();

    return ((MemoryStream)compressor)
        .ToArray();
}

For production HTTP benchmarking, however, measure the actual ASP.NET Core response path as well.

Application-level compression performance can differ from isolated algorithm performance because the real pipeline includes serialization, middleware, buffering, transport, and networking.

Compare Results

A benchmark report should include at least:

MetricNo CompressionGzipBrotliZstandard
Original SizeXXXX
Compressed SizeXXXX
Reduction0%X%X%X%
p50XXXX
p95XXXX
p99XXXX
CPUXXXX
ThroughputXXXX

Populate the table with measurements from your own environment.

Find the Compression Break-Even Point

One of the most useful outcomes is determining when compression becomes beneficial.

For example, you may discover:

< 20 KB
Compression adds overhead

20–100 KB
Compression begins to help

100 KB–1 MB
Compression provides strong network savings

> 1 MB
Compression provides substantial bandwidth reduction

These thresholds are illustrative only.

The correct break-even point depends on:

  • CPU

  • Network bandwidth

  • Payload structure

  • Compression algorithm

  • Concurrency

  • Client performance

  • Hosting environment

Measure Bandwidth Savings

Suppose an API serves:

100 requests/sec

with:

2 MB uncompressed response

That is approximately:

200 MB/sec

of response data.

If compression reduces the response to 300 KB:

100 × 300 KB
≈ 30 MB/sec

The network requirement changes dramatically.

This can affect:

  • Cloud egress

  • Load balancer capacity

  • CDN traffic

  • Mobile performance

  • Inter-region traffic

Cost Considerations

For large APIs, bandwidth can become a meaningful infrastructure cost.

Compression can reduce transmitted bytes, but CPU utilization may increase.

Therefore, evaluate:

Bandwidth Cost Saved
        -
Additional Compute Cost
        =
Net Infrastructure Impact

Do not optimize one dimension without measuring the other.

Watch for Double Compression

A common deployment mistake occurs when multiple layers attempt to compress the same response.

For example:

ASP.NET Core
     |
     v
Reverse Proxy
     |
     v
CDN

If more than one layer is responsible for compression, verify the behavior carefully.

The response should not be repeatedly compressed or incorrectly labeled.

Check:

Content-Encoding
Vary

and inspect the actual response bytes.

The Vary Header

Compression negotiation can depend on Accept-Encoding.

Caching infrastructure therefore needs to distinguish compressed and uncompressed variants appropriately.

A response may use:

Vary: Accept-Encoding

This tells caches that the response representation can vary based on the request's encoding capabilities.

Caching behavior should be included in production validation.

Security Considerations

Compression has security implications in some application designs.

One important class of concern occurs when sensitive data and attacker-controlled data are compressed together and an attacker can observe response-size changes.

The classic concern is not that compression itself is insecure, but that compression can sometimes create side-channel opportunities.

For sensitive endpoints:

  • Avoid unnecessary reflection of secrets.

  • Do not blindly compress every response.

  • Review responses containing secrets alongside attacker-controlled input.

  • Follow your organization's security guidance for compression-sensitive endpoints.

Common Mistakes

Benchmarking Only Payload Size

A smaller payload does not automatically mean a faster or cheaper API.

Measuring Only Average Latency

Tail latency matters for production workloads.

Using Unrealistic JSON

Highly repetitive synthetic data can produce misleadingly strong compression ratios.

Ignoring CPU

Compression trades network bandwidth for compute.

Testing Only One Payload Size

Compression behavior changes significantly with response size.

Forgetting the Client Header

If Accept-Encoding is not configured correctly, you may not be testing compression at all.

Ignoring Proxies

Reverse proxies and CDNs can change the effective compression path.

Benchmarking a Single Request

Single-request measurements do not reveal concurrency behavior.

Mixing Serialization and Compression Metrics

A slow endpoint may be slow because JSON serialization dominates rather than compression.

Using Global Conclusions From One Environment

Results from a developer workstation do not necessarily predict production behavior.

Advantages

Lower Network Usage

Compressed JSON can substantially reduce bytes transferred.

Better Performance on Slow Networks

Large responses can reach clients faster when bandwidth is the bottleneck.

Lower Egress Traffic

Reduced payload size can lower network transfer volume.

Better Mobile Experience

Smaller responses can be particularly useful on bandwidth-constrained connections.

Improved API Scalability

Reducing network traffic can relieve pressure on network infrastructure.

Disadvantages

Additional CPU Usage

Compression requires server-side processing.

Increased Complexity

Compression interacts with clients, proxies, caching, and transport protocols.

Variable Benefits

Small or high-entropy payloads may see limited gains.

Potential Tail-Latency Impact

Under heavy CPU pressure, compression can increase p95 or p99 latency.

Operational Tuning

Compression levels and algorithm selection may require workload-specific tuning.

Best Practices

  1. Establish an uncompressed baseline.

  2. Benchmark realistic JSON payloads.

  3. Test multiple payload sizes.

  4. Measure p50, p95, and p99 latency.

  5. Measure CPU and throughput at realistic concurrency.

  6. Verify the actual Content-Encoding response.

  7. Benchmark Gzip and Brotli, and evaluate Zstandard where your stack supports it.

  8. Test both repetitive and high-entropy payloads.

  9. Separate serialization cost from compression cost.

  10. Benchmark HTTPS and the production HTTP protocol.

  11. Test through the same proxy or gateway path used in production.

  12. Evaluate compression levels rather than assuming the highest level is best.

  13. Measure bandwidth savings and infrastructure cost.

  14. Validate caching behavior and Vary: Accept-Encoding.

  15. Watch for double compression across infrastructure layers.

  16. Test cold and warm workloads separately.

  17. Include concurrency in the benchmark.

  18. Establish a workload-specific break-even point.

  19. Treat compression as a performance trade-off rather than an automatic optimization.

  20. Re-run benchmarks after changing runtime, hosting, payload structure, or infrastructure configuration.

Frequently Asked Questions

Does compression always make an API faster?

No. Compression can make large responses faster when network transfer is the bottleneck, but the CPU cost can outweigh the network savings for small responses or very fast networks.

Which is better, Gzip or Brotli?

There is no universal winner. Brotli can provide strong compression for text, while Gzip has broad compatibility and mature tooling. Benchmark both with your actual payloads.

Is Zstandard always faster?

No. Algorithm performance depends on compression level, implementation, payload characteristics, CPU, and the surrounding HTTP stack. It should be benchmarked rather than assumed to be superior.

Should every JSON API response be compressed?

Not necessarily. Small responses may not justify the overhead. Compression policies should consider response size, content type, CPU availability, and security requirements.

Does compression reduce JSON serialization time?

No. Serialization happens before compression. Compression can reduce network transfer time, but it does not inherently make the serializer faster.

How large should a response be before compression is enabled?

There is no universal threshold. Benchmark your workload and identify the point where network savings exceed compression overhead.

Does compression help with HTTP/2 and HTTP/3?

Yes, response-body compression can still reduce the amount of application data transferred. However, HTTP/2 and HTTP/3 have different transport characteristics, so production workloads should be benchmarked directly.

Can compression reduce cloud costs?

Potentially. If network transfer or egress volume is significant, reducing response bytes can reduce bandwidth consumption. The resulting compute cost of compression should also be measured.

Conclusion

HTTP compression is a classic example of a performance optimization that needs measurement rather than assumptions.

For large JSON APIs, compression can dramatically reduce response size and network traffic. But the benefit comes with CPU overhead, and the optimal configuration depends on payload structure, response size, concurrency, network conditions, transport protocol, and infrastructure.

A useful benchmark should therefore measure the complete path:

Application
    |
    v
JSON Serialization
    |
    v
Compression
    |
    v
HTTP Transport
    |
    v
Network
    |
    v
Client

The most valuable result is not simply identifying the algorithm that produces the smallest response.

Instead, determine the configuration that provides the best balance of:

Payload Reduction
+
Latency
+
CPU Efficiency
+
Throughput
+
Infrastructure Cost

For .NET 11 applications serving large JSON responses, this benchmark-driven approach makes compression decisions much more defensible. Rather than enabling the strongest compression everywhere, teams can establish workload-specific thresholds, choose appropriate algorithms, and understand exactly where compression improves the system and where it simply adds CPU overhead.