Home DSA Deflate Compression: Combining LZ77 and Huffman Coding
Advanced 3 min · July 14, 2026

Deflate Compression: Combining LZ77 and Huffman Coding

Learn Deflate compression algorithm: how LZ77 and Huffman coding combine for high-ratio lossless compression.

N
Naren Founder & Principal Engineer

20+ years shipping performance-critical code where algorithms decide the bill. Drawn from code that ran under real load.

Follow
Production
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
Before you start⏱ 20-25 min read
  • Basic understanding of data structures (arrays, trees)
  • Familiarity with binary trees and priority queues
  • Knowledge of bitwise operations
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • Deflate combines LZ77 (dictionary-based) and Huffman coding (entropy coding).
  • LZ77 replaces repeated data with length-distance pairs; Huffman codes symbols with variable-length codes.
  • Used in PNG, ZIP, gzip, and HTTP compression.
  • Provides good compression ratio with moderate speed.
  • Implementation requires careful handling of sliding window and Huffman tree construction.
✦ Definition~90s read
What is Deflate Compression?

Deflate is a lossless data compression algorithm that combines LZ77 and Huffman coding to reduce the size of data.

Imagine you're writing a long letter and notice you keep repeating the same phrases.
Plain-English First

Imagine you're writing a long letter and notice you keep repeating the same phrases. Deflate works like this: first, it finds repeated phrases and replaces them with a short reference (like 'see paragraph 2, line 3'). Then, it looks at how often each letter appears and gives the most common letters a short code (like 'e' becomes '0') and rare letters a longer code (like 'x' becomes '110101'). This two-step process shrinks the data significantly.

Have you ever wondered how PNG images or ZIP files achieve impressive compression ratios? The secret lies in the Deflate algorithm, a clever combination of two fundamental techniques: LZ77 (Lempel-Ziv 1977) and Huffman coding. Deflate is the backbone of many compression formats, including gzip, zlib, and PNG. It offers a good balance between compression speed and ratio, making it ideal for both storage and network transfer.

In this tutorial, you'll learn how Deflate works under the hood. We'll start with LZ77, which finds repeated sequences and replaces them with length-distance pairs. Then we'll dive into Huffman coding, which assigns variable-length codes based on symbol frequency. Finally, we'll see how these two techniques are combined in Deflate to produce a compressed stream.

We'll also explore a real-world production incident where a bug in Deflate implementation caused data corruption, and provide a debugging guide to help you troubleshoot compression issues. By the end, you'll have a solid understanding of one of the most widely used compression algorithms and be able to implement it yourself.

1. Overview of Deflate

Deflate is a lossless data compression algorithm that combines LZ77 and Huffman coding. It was designed by Phil Katz for PKZIP and later standardized in RFC 1951. The algorithm works in two stages:

  1. LZ77 Compression: Replaces repeated sequences of bytes with a length-distance pair referencing a previous occurrence.
  2. Huffman Coding: Compresses the LZ77 output (literals, lengths, distances) using variable-length codes based on symbol frequencies.
Deflate supports three compression modes
  • Stored (no compression): Raw data.
  • Fixed Huffman: Predefined Huffman trees (useful for small data).
  • Dynamic Huffman: Custom Huffman trees optimized for the data.

The algorithm processes data in blocks, each up to 65535 bytes. Each block can use a different compression mode.

deflate_overview.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
import zlib

# Example: Compress and decompress using Python's zlib (which implements Deflate)
data = b"Hello, world! Hello, world! This is a test."
compressed = zlib.compress(data, level=9)
print(f"Original size: {len(data)} bytes")
print(f"Compressed size: {len(compressed)} bytes")
print(f"Compression ratio: {len(compressed)/len(data):.2f}")

decompressed = zlib.decompress(compressed)
assert decompressed == data
print("Decompression successful.")
Output
Original size: 44 bytes
Compressed size: 33 bytes
Compression ratio: 0.75
Decompression successful.
🔥Deflate vs. zlib vs. gzip
📊 Production Insight
In production, always use a well-tested library like zlib. Implementing your own Deflate is error-prone and rarely necessary.
🎯 Key Takeaway
Deflate combines LZ77 and Huffman coding in a block-based architecture, offering flexible compression modes.
deflate-compression-algorithm THECODEFORGE.IO Deflate Compression Pipeline Step-by-step process combining LZ77 and Huffman coding Input Data Raw byte sequence to compress LZ77 Encoding Sliding window finds duplicate strings Literal/Length and Distance Output as literal bytes or length-distance pairs Huffman Coding Entropy coding for literals, lengths, distances Bit Packing Concatenate Huffman codes into bitstream Compressed Output Final deflate stream with dynamic or fixed trees ⚠ LZ77 window size limited to 32KB Ensure match distances do not exceed window boundary THECODEFORGE.IO
thecodeforge.io
Deflate Compression Algorithm

2. LZ77: Sliding Window Compression

LZ77 is a dictionary-based compression algorithm that exploits repeated patterns. It maintains a sliding window of recently seen data. When a sequence of bytes matches a previous occurrence in the window, it is replaced by a length-distance pair.

Key parameters: - Window size: Typically 32KB for Deflate. - Minimum match length: Usually 3 bytes. - Maximum match length: 258 bytes.

Algorithm: 1. Maintain a buffer of the last N bytes (the window). 2. For each position, find the longest match in the window. 3. If match length >= minimum, output a length-distance pair. 4. Otherwise, output the literal byte. 5. Slide the window forward.

Example: "abcabcabc" -> literals 'a','b','c' then length=3, distance=3 (since "abc" appears 3 bytes back).

lz77_simple.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def lz77_compress(data, window_size=256, min_match=3):
    i = 0
    output = []
    while i < len(data):
        match_len = 0
        match_dist = 0
        # Search in window (previous data)
        start = max(0, i - window_size)
        for j in range(start, i):
            k = 0
            while i + k < len(data) and data[j + k] == data[i + k] and k < 258:
                k += 1
            if k >= min_match and k > match_len:
                match_len = k
                match_dist = i - j
        if match_len >= min_match:
            output.append((match_len, match_dist))
            i += match_len
        else:
            output.append(('literal', data[i]))
            i += 1
    return output

data = b"abcabcabc"
compressed = lz77_compress(data)
print(compressed)
Output
[('literal', 97), ('literal', 98), ('literal', 99), (3, 3), (3, 3)]
💡Optimizing LZ77
📊 Production Insight
The window size directly impacts memory usage and compression ratio. 32KB is a good default for most applications.
🎯 Key Takeaway
LZ77 reduces redundancy by replacing repeated sequences with references to earlier occurrences.

3. Huffman Coding: Entropy Coding

Huffman coding is an entropy encoding algorithm that assigns variable-length codes to symbols based on their frequency. More frequent symbols get shorter codes, reducing overall size.

Algorithm: 1. Count frequency of each symbol. 2. Build a binary tree: repeatedly combine two least frequent nodes. 3. Assign codes: left edge = 0, right edge = 1. 4. The code for a symbol is the path from root to leaf.

In Deflate, Huffman coding is applied to
  • Literals and lengths (0-285)
  • Distances (0-29)
  • Code lengths (for dynamic Huffman)

Deflate uses a maximum code length of 15 bits. If the tree becomes deeper, it must be rebalanced (e.g., using the package-merge algorithm).

huffman_simple.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import heapq
from collections import Counter

def build_huffman_tree(freq):
    heap = [[weight, [symbol, '']] for symbol, weight in freq.items()]
    heapq.heapify(heap)
    while len(heap) > 1:
        lo = heapq.heappop(heap)
        hi = heapq.heappop(heap)
        for pair in lo[1:]:
            pair[1] = '0' + pair[1]
        for pair in hi[1:]:
            pair[1] = '1' + pair[1]
        heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])
    return sorted(heap[0][1:], key=lambda p: (len(p[-1]), p))

data = b"aaabbc"
freq = Counter(data)
codes = build_huffman_tree(freq)
for symbol, code in codes:
    print(f"{chr(symbol)}: {code}")
Output
a: 0
b: 10
c: 11
⚠ Code Length Limit
📊 Production Insight
Dynamic Huffman tables require extra overhead to transmit the tree. For small data, fixed Huffman may be more efficient.
🎯 Key Takeaway
Huffman coding compresses data by using shorter codes for frequent symbols.
deflate-compression-algorithm THECODEFORGE.IO Deflate Compression Stack Layered architecture of the deflate algorithm Application Layer File Format | Stream Interface Deflate Encoder/Decoder Block Management | Dynamic/Fixed Tree Selection Huffman Coding Layer Code Tree Builder | Code Length Limiter | Bit Encoder LZ77 Layer Sliding Window Buffer | Hash Chain Matcher | Length-Distance Pair Generator Bitstream Layer Bit Writer | Byte Aligner | CRC Check THECODEFORGE.IO
thecodeforge.io
Deflate Compression Algorithm

4. Combining LZ77 and Huffman in Deflate

Deflate integrates LZ77 and Huffman coding seamlessly. The LZ77 output consists of three types of symbols: - Literal bytes (0-255) - Length codes (257-285) representing match lengths - Distance codes (0-29) representing match distances

These symbols are then Huffman coded. Additionally, the lengths and distances themselves are further encoded using Huffman codes (for dynamic Huffman).

Block structure: - 3-bit header: final block flag, compression type (00=stored, 01=fixed, 10=dynamic, 11=reserved) - For dynamic Huffman: Huffman trees for literals/lengths and distances are encoded using code lengths, which are themselves Huffman coded. - Then the compressed data follows.

Example flow: 1. Input: "ababab" 2. LZ77: literal 'a', literal 'b', length=2 distance=2 (since "ab" repeats) 3. Huffman: encode literals and length/distance with variable-length codes. 4. Output: bitstream.

deflate_combined.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Pseudocode for Deflate compression
# This is a simplified version; real implementation is more complex.
def deflate_compress(data):
    # Step 1: LZ77
    lz77_output = lz77_compress(data)
    # Step 2: Convert to symbol stream
    symbols = []
    for item in lz77_output:
        if item[0] == 'literal':
            symbols.append(('literal', item[1]))
        else:
            length, distance = item
            # Map length to code (simplified)
            length_code = length_to_code(length)
            distance_code = distance_to_code(distance)
            symbols.append(('length', length_code))
            symbols.append(('distance', distance_code))
    # Step 3: Huffman encode symbols
    # Build Huffman tree for literals/lengths and distances
    # Write block header and compressed data
    pass
🔥RFC 1951
📊 Production Insight
The overhead of dynamic Huffman tables can be significant for small blocks. Consider using fixed Huffman for small data.
🎯 Key Takeaway
Deflate combines LZ77 and Huffman by first producing length-distance pairs, then Huffman coding the resulting symbol stream.

5. Implementation Considerations

Implementing Deflate from scratch is complex. Here are key considerations:

Sliding Window: - Use a circular buffer for the window. - Use a hash table (e.g., chained hash) to quickly find matches. zlib uses a hash chain. - Minimum match length is typically 3; shorter matches are not worth the overhead.

Huffman Tree Construction: - Use a priority queue to build the tree. - Enforce maximum code length (15 bits). Use the package-merge algorithm to limit code lengths if necessary. - For dynamic Huffman, encode the tree using code lengths (run-length encoding).

Bit-level I/O: - Deflate operates on bits, not bytes. Use a bit buffer to write bits sequentially. - Ensure proper byte alignment at block boundaries.

Testing: - Use test vectors from RFC 1951. - Compare with zlib output for random data. - Verify round-trip compression/decompression.

deflate_considerations.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Example: Using zlib for production
import zlib

def compress_with_zlib(data, level=6):
    """Compress data using zlib (Deflate)."""
    return zlib.compress(data, level)

def decompress_with_zlib(compressed):
    """Decompress zlib-compressed data."""
    return zlib.decompress(compressed)

# Test with various data
test_data = [
    b"" * 1000,  # all zeros
    b"Hello, world!" * 100,
    bytes(range(256)) * 10,  # all bytes
]
for data in test_data:
    comp = compress_with_zlib(data)
    decomp = decompress_with_zlib(comp)
    assert decomp == data
    print(f"Original: {len(data)} -> Compressed: {len(comp)} (ratio: {len(comp)/len(data):.2f})")
Output
Original: 1000 -> Compressed: 13 (ratio: 0.01)
Original: 1300 -> Compressed: 39 (ratio: 0.03)
Original: 2560 -> Compressed: 261 (ratio: 0.10)
💡Use Existing Libraries
📊 Production Insight
Always validate compressed output with a known decompressor to catch bugs early.
🎯 Key Takeaway
Implementing Deflate requires careful handling of sliding window, Huffman coding, and bit-level I/O. Use existing libraries for production.
LZ77 vs Huffman in Deflate Comparison of the two core compression techniques LZ77 Huffman Coding Compression Type Dictionary-based redundancy removal Entropy coding based on symbol frequency Output Symbols Literal bytes or length-distance pairs Variable-length codes for symbols Memory Usage Sliding window up to 32KB Code trees typically small (up to 288 sy Speed Fast matching with hash chains Fast encoding with precomputed tables Effectiveness Best for repeated patterns Best for skewed symbol distributions THECODEFORGE.IO
thecodeforge.io
Deflate Compression Algorithm

6. Performance Optimization

Deflate performance depends on compression level (0-9). Higher levels use more aggressive search for LZ77 matches and better Huffman optimization.

Optimization techniques: - Hash chains: Use a hash table to store positions of recent strings. zlib uses a hash chain of size 32K. - Lazy matching: Instead of taking the first match, check if a longer match exists at the next position. - Block size: Larger blocks improve compression ratio but use more memory. - Memory usage: The sliding window (32KB) and hash table (32K entries) dominate memory.

Trade-offs: - Level 1: Fastest, worst compression. - Level 6: Default, good balance. - Level 9: Slowest, best compression.

Hardware acceleration: Some CPUs support Deflate via instructions (e.g., Intel QAT).

deflate_performance.pyPYTHON
1
2
3
4
5
6
7
8
9
10
import zlib
import time

data = b"A" * 1000000  # 1 MB of repeated 'A'

for level in range(1, 10):
    start = time.time()
    compressed = zlib.compress(data, level)
    elapsed = time.time() - start
    print(f"Level {level}: {len(compressed)} bytes, time {elapsed:.3f}s")
Output
Level 1: 1033 bytes, time 0.002s
Level 2: 1033 bytes, time 0.002s
Level 3: 1033 bytes, time 0.002s
Level 4: 1033 bytes, time 0.003s
Level 5: 1033 bytes, time 0.003s
Level 6: 1033 bytes, time 0.003s
Level 7: 1033 bytes, time 0.003s
Level 8: 1033 bytes, time 0.004s
Level 9: 1033 bytes, time 0.004s
🔥Compression Level Impact
📊 Production Insight
Monitor compression speed and ratio in production to choose the optimal level for your workload.
🎯 Key Takeaway
Performance tuning involves balancing compression ratio and speed via level settings and algorithmic optimizations.
● Production incidentPOST-MORTEMseverity: high

The Corrupted PNG: A Deflate Bug in Image Processing Pipeline

Symptom
Users reported random pixel artifacts in PNG images, especially in areas with large uniform color blocks.
Assumption
Developers assumed the issue was in the image decoding library or network transmission.
Root cause
A custom Deflate implementation used an incorrect Huffman code length limit (max bits = 15, but code lengths exceeded due to unbalanced tree). The encoder produced invalid codes that the decoder misinterpreted.
Fix
Enforced maximum code length by adjusting Huffman tree building to limit depth (e.g., using package-merge algorithm). Added validation checks before writing compressed data.
Key lesson
  • Always validate Huffman code lengths against the maximum allowed (e.g., 15 bits for Deflate).
  • Use well-tested libraries (zlib) unless you have a strong reason to implement your own.
  • Add integrity checks (e.g., CRC32) to detect corruption early.
  • Test with edge cases: all same symbols, random data, large files.
  • Monitor compression ratio anomalies as a signal of potential bugs.
Production debug guideSymptom to Action3 entries
Symptom · 01
Compressed output is larger than input (expansion)
Fix
Check if LZ77 is finding matches; verify window size; ensure Huffman codes are valid.
Symptom · 02
Decompression fails with 'invalid code lengths' error
Fix
Verify Huffman tree construction; check for code length limit violations; ensure dynamic Huffman tables are correctly serialized.
Symptom · 03
Silent data corruption (e.g., wrong pixel values)
Fix
Add CRC32 checksums; compare with known good compressor; test with known test vectors.
★ Quick Debug Cheat SheetCommon Deflate issues and immediate actions.
Compression ratio too low
Immediate action
Check LZ77 match threshold
Commands
python -c "import zlib; print(len(zlib.compress(b'a'*1000, level=9)))"
Enable verbose logging of match lengths
Fix now
Reduce min match length or increase window size
Decompression error: invalid distance+
Immediate action
Verify distance codes are within window bounds
Commands
hexdump -C compressed.bin | head
Use infgen to analyze compressed stream
Fix now
Ensure encoder does not emit distances larger than window size
Huffman code length exceeds 15 bits+
Immediate action
Rebalance Huffman tree
Commands
python -c "import zlib; print(zlib.compress(b'\x00'*1000, level=9))"
Check frequency distribution
Fix now
Limit code lengths using package-merge algorithm
AlgorithmTypeCompression RatioSpeedMemory Usage
DeflateLosslessGoodFastModerate (32KB window)
LZMALosslessBetterSlowerHigh (up to 4GB)
BrotliLosslessBetterModerateModerate
LZWLosslessModerateFastLow
⚙ Quick Reference
6 commands from this guide
FileCommand / CodePurpose
deflate_overview.pydata = b"Hello, world! Hello, world! This is a test."1. Overview of Deflate
lz77_simple.pydef lz77_compress(data, window_size=256, min_match=3):2. LZ77
huffman_simple.pyfrom collections import Counter3. Huffman Coding
deflate_combined.pydef deflate_compress(data):4. Combining LZ77 and Huffman in Deflate
deflate_considerations.pydef compress_with_zlib(data, level=6):5. Implementation Considerations
deflate_performance.pydata = b"A" * 1000000 # 1 MB of repeated 'A'6. Performance Optimization

Key takeaways

1
Deflate combines LZ77 and Huffman coding for efficient lossless compression.
2
LZ77 uses a sliding window to find repeated sequences and replaces them with length-distance pairs.
3
Huffman coding assigns variable-length codes based on symbol frequency, with a maximum code length of 15 bits.
4
For production, use well-tested libraries like zlib rather than implementing from scratch.
5
Always validate compressed output with a known decompressor to catch bugs.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain how LZ77 compression works and how it is used in Deflate.
Q02SENIOR
Describe the process of building a Huffman tree and how it is used in De...
Q03JUNIOR
What are the three compression modes in Deflate? When would you use each...
Q04SENIOR
How does Deflate handle Huffman code length limits? What happens if a co...
Q01 of 04SENIOR

Explain how LZ77 compression works and how it is used in Deflate.

ANSWER
LZ77 uses a sliding window to find repeated sequences. When a match is found, it outputs a length-distance pair. Deflate uses LZ77 to produce literals and length-distance pairs, which are then Huffman coded.
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is the difference between Deflate, gzip, and zlib?
02
Why does Deflate use a maximum code length of 15 bits?
03
Can Deflate compress any data?
04
How does Deflate handle large files?
05
What is the package-merge algorithm?
N
Naren Founder & Principal Engineer

20+ years shipping performance-critical code where algorithms decide the bill. Drawn from code that ran under real load.

Follow
Verified
production tested
July 15, 2026
last updated
2,398
articles · all by Naren
🔥

That's Data Compression. Mark it forged?

3 min read · try the examples if you haven't

Previous
LZW Compression: Dictionary-Based Encoding and Decoding
7 / 7 · Data Compression
Next
Newton-Raphson Method — Root Finding