flashman
← All guides

Streaming Base64 without corrupting byte boundaries

Stream Base64 safely by carrying incomplete byte groups, separating transport chunks from messages, bounding memory, and verifying exact byte round trips.

2026-09-08 · 8 min read

  • base64
  • streaming
  • data-integrity

Base64 encodes each three input bytes as four characters. Stream chunks supplied by a filesystem, network, or compression layer can end after any byte, so independently encoding and concatenating those chunks is not generally equivalent to encoding the full byte stream.

A stateful encoder retains zero, one, or two input bytes until enough data arrives. Only finalization decides whether padding is needed for the last group.

Define framing before implementation

Decide whether the protocol carries one continuous Base64 value or a sequence of independently framed values. Transport chunk boundaries are implementation details and must not silently become message boundaries.

  • Specify the standard or URL-safe alphabet.
  • Specify required, optional, or forbidden final padding.
  • Define whether whitespace is accepted or rejected.
  • Bound encoded and decoded sizes before allocation.

Preserve byte and backpressure semantics

Feed binary byte arrays to the encoder and keep character decoding out of the binary path. Propagate backpressure so a slow destination does not cause the process to accumulate the complete expanded output in memory.

Base64 expands data to roughly four thirds of its original size before wrappers and framing. Incremental decoding also needs an explicit maximum decoded size because a compact input can still exceed an application's memory or storage budget.

Handle retries and errors at stable boundaries

A retry needs a byte offset or application frame that both sides understand. Restarting in the middle of a Base64 quartet without encoder state can duplicate or corrupt bytes.

  • Finalize exactly once after the final input byte.
  • Reject data after terminal padding in a strict profile.
  • Cancel upstream reads when decoding fails.
  • Verify integrity separately from successful decoding.

Create chunk-invariant tests

Use Flashman's Base64 tool for public fixtures, hash tool for exact input and output digests, diff to locate corruption, units converter for size budgets, and JSON formatter when an application frames encoded messages.

Encode the same fixture with every split around three-byte boundaries and compare output and decoded bytes. Cover empty input, one- and two-byte tails, strict padding, URL-safe alphabets, whitespace, backpressure, cancellation, retries, malformed input, and large streams.

Try these tools