Skip to main content

Compression Guide

Learn how to compress and decompress data in your Invoke functions.

Overview

import zlib from 'zlib'

export default function handler(req, res) {
const data = 'Hello World! '.repeat(100)
const compressed = zlib.gzipSync(data)
const decompressed = zlib.gunzipSync(compressed)

res.json({
original: data.length,
compressed: compressed.length,
ratio: ((compressed.length / data.length) * 100).toFixed(2) + '%'
})
}

Gzip Compression

Synchronous

import zlib from 'zlib'

export default function handler(req, res) {
const data = 'Hello World! '.repeat(100)
const compressed = zlib.gzipSync(data)
const decompressed = zlib.gunzipSync(compressed)

res.json({
original: data.length,
compressed: compressed.length,
ratio: ((compressed.length / data.length) * 100).toFixed(2) + '%',
decompressed: decompressed.toString()
})
}

Streaming

import zlib from 'zlib'
import { Readable } from 'stream'

export default async function handler(req, res) {
const chunks = []
const source = Readable.from(['chunk 1 ', 'chunk 2 ', 'chunk 3'])
const gzip = zlib.createGzip()

for await (const chunk of source.pipe(gzip)) {
chunks.push(chunk)
}

const compressed = Buffer.concat(chunks)
res.setHeader('Content-Encoding', 'gzip')
res.setHeader('Content-Type', 'text/plain')
res.send(compressed)
}

Deflate Compression

import zlib from 'zlib'

export default function handler(req, res) {
const data = Buffer.from(req.body.data)
const compressed = zlib.deflateSync(data)
const decompressed = zlib.inflateSync(compressed)

res.json({
original: data.length,
compressed: compressed.length,
decompressed: decompressed.toString()
})
}

Brotli Compression

import zlib from 'zlib'

export default function handler(req, res) {
const data = 'Large data...'.repeat(1000)
const compressed = zlib.brotliCompressSync(data)
const decompressed = zlib.brotliDecompressSync(compressed)

res.json({
original: data.length,
compressed: compressed.length,
ratio: ((compressed.length / data.length) * 100).toFixed(2) + '%'
})
}

Compressing JSON

import zlib from 'zlib'

export default async function handler(req, res) {
const data = {
users: Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `User ${i}`,
email: `user${i}@example.com`
}))
}

const json = JSON.stringify(data)
const compressed = zlib.gzipSync(json)

await kv.set('users:compressed', compressed.toString('base64'))

res.json({
originalSize: json.length,
compressedSize: compressed.length,
savings: ((1 - compressed.length / json.length) * 100).toFixed(2) + '%'
})
}

Decompressing JSON

import zlib from 'zlib'

export default async function handler(req, res) {
const compressedBase64 = await kv.get('users:compressed')
const compressed = Buffer.from(compressedBase64, 'base64')
const decompressed = zlib.gunzipSync(compressed)

res.json(JSON.parse(decompressed.toString()))
}

HTTP Response Compression

import zlib from 'zlib'

export default function handler(req, res) {
const data = { message: 'Large response data...' }
const json = JSON.stringify(data)
const acceptEncoding = req.get('Accept-Encoding') || ''

if (acceptEncoding.includes('gzip')) {
const compressed = zlib.gzipSync(json)
res.setHeader('Content-Encoding', 'gzip')
res.setHeader('Content-Type', 'application/json')
res.send(compressed)
} else {
res.json(data)
}
}

Compression Levels

import zlib from 'zlib'

export default function handler(req, res) {
const data = 'Data to compress'.repeat(100)
const results = {}

for (let level = 0; level <= 9; level++) {
const compressed = zlib.gzipSync(data, { level })
results[`level_${level}`] = {
size: compressed.length,
ratio: ((compressed.length / data.length) * 100).toFixed(2) + '%'
}
}

res.json(results)
}

Best Compression Algorithm Comparison

import zlib from 'zlib'

export default function handler(req, res) {
const data = req.body.data || 'Test data'.repeat(1000)
const gzipped = zlib.gzipSync(data)
const deflated = zlib.deflateSync(data)
const brotli = zlib.brotliCompressSync(data)

res.json({
original: data.length,
gzip: { size: gzipped.length, ratio: ((gzipped.length / data.length) * 100).toFixed(2) + '%' },
deflate: { size: deflated.length, ratio: ((deflated.length / data.length) * 100).toFixed(2) + '%' },
brotli: { size: brotli.length, ratio: ((brotli.length / data.length) * 100).toFixed(2) + '%' }
})
}

Error Handling

import zlib from 'zlib'

export default function handler(req, res) {
try {
const compressed = Buffer.from(req.body.data, 'base64')
const decompressed = zlib.gunzipSync(compressed)
res.send(decompressed.toString())
} catch (error) {
if (error.code === 'Z_DATA_ERROR') {
res.status(400).json({ error: 'Invalid compressed data' })
} else {
res.status(500).json({ error: 'Decompression failed' })
}
}
}

Use Cases

1. Compressing Large KV Store Values

import zlib from 'zlib'

export default async function handler(req, res) {
const largeData = {
/* large object */
}
const compressed = zlib.gzipSync(JSON.stringify(largeData))
await kv.set('large:data', compressed.toString('base64'))
res.json({ stored: true })
}

2. API Response Caching

import zlib from 'zlib'

export default async function handler(req, res) {
const cacheKey = 'api:response'
const cached = await kv.get(cacheKey)

if (cached) {
const decompressed = zlib.gunzipSync(Buffer.from(cached, 'base64'))
return res.json(JSON.parse(decompressed.toString()))
}

const response = await fetch('https://api.example.com/large-data')
const data = await response.json()
const compressed = zlib.gzipSync(JSON.stringify(data))

await kv.set(cacheKey, compressed.toString('base64'), 3600000)
res.json(data)
}

Best Practices

1. Choose Right Algorithm

  • Gzip: Best balance, wide support
  • Deflate: Similar to gzip, less overhead
  • Brotli: Best compression, slightly slower

2. Consider Compression Level

LevelBun (zlib)C# (CompressionLevel)
Fastlevel: 1Fastest
Defaultlevel: 6Optimal
Bestlevel: 9SmallestSize

3. Only Compress Large Data

if (data.length > 1024) {
compressed = zlib.gzipSync(data)
}

Next Steps