Careeroza
Compression and HTTP Tuning
Response Compression
JSON compresses very well. A 120 KB product list becomes about 15 KB with gzip, which matters on Indian mobile networks.
Example
application.yml
server:
compression:
enabled: true
mime-types: application/json,text/html,text/css,application/javascript,text/csv
min-response-size: 1KB
http2:
enabled: true
tomcat:
threads:
max: 200
connection-timeout: 5sExample
curl -s -o /dev/null -w "%{size_download}\n" localhost:8080/api/products?size=100
curl -s -o /dev/null -w "%{size_download}\n" -H "Accept-Encoding: gzip" localhost:8080/api/products?size=100Example output
122841 15276
Gzip in Plain Java
Example
See the effect with java.util.zip on a repetitive JSON payload:
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;
public class Main {
public static void main(String[] args) throws IOException {
StringBuilder json = new StringBuilder("[");
for (int i = 1; i <= 500; i++) {
if (i > 1) json.append(',');
json.append("{\"id\":").append(i)
.append(",\"name\":\"Cotton T-Shirt size M\",\"price\":499.00,\"category\":\"fashion\",\"stock\":")
.append(i % 50).append('}');
}
json.append(']');
byte[] raw = json.toString().getBytes(StandardCharsets.UTF_8);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (GZIPOutputStream gz = new GZIPOutputStream(out)) { gz.write(raw); }
System.out.println("raw bytes: " + raw.length);
System.out.println("gzipped bytes: " + out.size());
System.out.printf("saved: %.0f%%%n", 100.0 * (raw.length - out.size()) / raw.length);
}
}Output
raw bytes: 44293 gzipped bytes: 1683 saved: 96%
HTTP Caching Headers
@GetMapping("/api/categories")
public ResponseEntity<List<CategoryDto>> categories() {
List<CategoryDto> list = categoryService.findAll();
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(Duration.ofMinutes(10)).cachePublic())
.eTag(Integer.toHexString(list.hashCode()))
.body(list);
}With an ETag, the browser sends If-None-Match next time and gets 304 Not Modified with an empty body if nothing changed. Add ShallowEtagHeaderFilter to do this for every GET automatically.