skip to content

questions

27

What distinguishes a text encoding from a binary encoding on the wire, and what does each choice cost?

level: juniorimportance: must knowfreq 72%

answer

  1. same values, different audience
  2. characters versus sized bytes
  3. grep, diff, hand-edit
  4. readability paid in bytes and CPU
  5. volume of the hop decides

basics

~20 s

A text encoding writes values as readable characters you can grep, diff and hand-edit; a binary encoding packs them as raw sized bytes that are typically smaller and cheaper to parse, but unreadable without a decoder.

solid answer

~50 s

Both carry the same values; they differ in whether the bytes are meant for a person as well as a machine. A **text encoding** spells every value out in characters — digits for numbers, characters for strings, punctuation for structure — so anything that reads characters can read it: a log line, a diff in a ticket, an editor. A **binary encoding** writes values in machine shape — fixed-width or variable-length integers, length-prefixed strings, numeric field tags — which is typically much smaller and cheaper to decode, but opaque without the matching decoder. So the axis is **inspectability against cost**: you pay for readability in bytes and processor time, and you pay for compactness in how hard the hop is to debug. Which side wins is usually decided by the volume of that hop and by whether a human ever reads those bytes.

go deeper

for a junior

Be able to say what each form looks like as bytes and name one concrete thing readability buys, such as grepping a captured message out of a log during an incident.

for a middle

Explain the mechanics behind the size and decode difference: spelled-out field names and punctuation against numeric tags and lengths, character scanning against sized reads.

for a senior

Argue the choice for a specific hop with rates and with who debugs it, and propose the hybrid where compact bytes travel but a rendering step keeps incident tooling readable.

for a principal

Frame it as a platform default rather than a per-service decision: what the organisation loses in debuggability across hundreds of hops, and what tooling must exist before a compact default is fair.

## What the two words mean on the wire Any value that leaves memory becomes a flat run of bytes. The question is what those bytes spell. In a **text encoding**, each value is represented with characters from a character set — in practice a UTF-8 compatible one. The number twelve hundred travels as the four characters `1200`. A string travels as its own characters, wrapped in whatever delimiters the grammar uses. Structure is punctuation: brackets, commas, indentation, angle brackets. Field names are usually spelled out next to every value. In a **binary encoding**, each value is written in a machine-shaped form. An integer is a fixed-width group of bytes or a variable-length one; a string is a length followed by its bytes; structure is carried by numeric tags, lengths and offsets instead of punctuation. Field names, if they exist at all, live in a separate definition rather than in the message. Both are just bytes. The real difference is whether the bytes were designed to be read by a person as well as by a program. ## What readability actually buys 1. **You can grep it.** A message that ends up in a log line, a trace attribute or an error report is searchable with ordinary tools. 2. **You can diff it.** Two captured messages can be pasted side by side in a ticket and the differing field is visible to anyone reading the ticket. 3. **You can hand-edit and replay it.** Reproducing a bug often means changing one field of a captured message and sending it again — trivial in characters, awkward in packed bytes. 4. **Any tool reads it.** No generated decoder, no schema fetch, no version match between the message and the reader's definitions. 5. **The first debugging step is shallow.** During an incident, the time between capturing a message and understanding it is close to zero, and that is exactly the moment when the cost of tooling is highest. ## What it costs | Axis | Text encoding | Binary encoding | | --- | --- | --- | | Read a captured message without tooling | Yes | No | | Bytes on the wire | Larger: digits, repeated field names, punctuation | Typically smaller: sized fields, numeric tags | | Decode work per value | Scan characters, find the end, convert digits | Read a known width, or skip by a stored length | | Reader needs an external definition | Usually not | Often yes | | Carrying raw bytes | Must be re-encoded into a safe character alphabet | Native | | Hand-editing a captured message | Practical | Impractical | Two honest qualifications belong in the answer. First, *typically* smaller is not *always* smaller: a small integer written as one character is smaller than the same value in a fixed-width eight-byte field. The compactness win comes from strings, repeated field names, punctuation and the ability to skip, not from every individual value. Second, whether a reader needs an external definition is a **separate axis** that merely correlates with this one — plenty of binary encodings describe themselves inline, and plenty of text messages are useless without a written contract. ## The cost is not only size Size is the part people quote, but decode work is often the part that bites. A text parser inspects characters one at a time to find where each value ends and then converts digit characters back into a number; a length-prefixed binary reader is told the width up front and can copy or skip without looking at the content. That is why compressing a text payload is not equivalent to going binary: it addresses the bytes on the link and leaves the processor cost on the receiver roughly where it was. ## Where the line falls in practice - **Low-volume, human-facing, or crossing an organisational boundary** — text almost always wins. The bytes cost nothing at that rate, and readability pays every time someone debugs it. - **A hot internal hop with large fan-out** — the arithmetic flips: the same message shape multiplied by a high rate makes size and decode cost real money, and the people debugging that hop can be given a decoder. - **Mixed, which is common** — a compact encoding on the hop plus a rendering step that turns captured messages back into characters for logs, traces and incident tooling. That buys most of the compactness without giving up inspectability where it is needed. ## How this is asked Interviewers are checking that you name the trade rather than recite a winner. - Name the axis first: inspectability against bytes and processor time. - Give the condition that decides it: the volume of the hop, and whether a human ever reads those bytes. - Avoid absolutes. A candidate who says binary is always better has not debugged a hop they could not read.

  • Is a text encoding always larger than a binary one for the same values?
    No. A small integer written as one or two characters is smaller than the same value in a fixed-width eight-byte field. The compactness of a binary encoding comes from packed strings with lengths, numeric tags instead of spelled-out field names, no punctuation and the ability to skip. Across realistic messages it usually wins comfortably, but the claim is statistical, not universal.
  • If readability is the point, why not keep text everywhere and simply compress it?
    That is often the right first move: a general-purpose compressor removes most of the redundancy of repeated field names and punctuation for very little engineering effort. What it does not remove is decode cost — the receiver still scans characters and re-parses numbers — and it does not make the compressed bytes readable either, so you keep readability only before compression and after decompression.

A parcel with a handwritten address label versus one carrying only a barcode. Both route correctly, but only one tells you where it is going when the scanner is unavailable.

saying these in an interview costs you the question

  • Says binary is always smaller and faster, naming no case where text wins
  • Treats text versus binary as the same axis as self-describing versus schema-driven
  • Believes a readable payload needs no written contract because you can see the fields
  • Cannot name anything operational that is lost when a hop stops being readable
  • Assumes compression makes the choice irrelevant for both size and decode cost
open as a page

Why can a program not write a value's in-memory bytes straight to a file for another process to read later?

level: juniorimportance: must knowfreq 72%

basics

~20 s

An in-memory value is laid out for one running process: it holds machine addresses valid only there, plus alignment holes whose contents are undefined. Another process shares none of that context, so the value must be re-expressed in a flat, self-standing form.

open as a page

Why must a binary wire format pin the byte order of its fixed-width integer fields instead of leaving it to each writer?

level: middleimportance: must knowfreq 66%

basics

~20 s

Because a multi-byte integer can be laid out most-significant byte first or least-significant byte first, and the two readings disagree: the bytes 00 00 00 01 mean 1 one way and 16,777,216 the other. Only the format can settle which.

open as a page

How does a base-128 varint use the top bit of each byte to encode an integer whose width the reader does not know in advance?

level: middleimportance: must knowfreq 62%

basics

~20 s

A base-128 varint carries seven payload bits per byte and spends the eighth as a continuation flag: set means another byte belongs to this number, clear means this is the last one. The reader stops at the first byte whose top bit is clear.

open as a page

How does a serializer that emits references by identifier keep a cyclic object graph from driving its encoder into unbounded recursion?

level: middleimportance: must knowfreq 58%

basics

~20 s

It keeps an identity-keyed map of nodes already written. A node's first visit assigns an identifier, recorded before recursing, and writes the body once; every later encounter writes only a reference, so no body is written twice.

open as a page

What does a tree-walking encoder produce, on the wire and after decode, when one build-graph node is reachable from three parents?

level: middleimportance: must knowfreq 66%

basics

~20 s

A tree walk writes that shared node's body once per path, so the wire carries three copies and decoding rebuilds three distinct objects with equal fields. Sharing is lost: a later change through one parent is invisible through the other two.

open as a page

What makes an encoding self-describing, and what must a reader of schema-driven bytes obtain before it can decode them?

level: middleimportance: must knowfreq 70%

basics

~20 s

Self-describing bytes carry their own structure: field identity and type travel beside the values, so any reader can parse them unaided. Schema-driven bytes carry values only, so the reader must first obtain the schema that says which value is which.

open as a page

Why does parsing a text-encoded message usually cost more processor time than reading a length-prefixed binary one?

level: middleimportance: must knowfreq 55%

basics

~20 s

Text parsing works character by character: it must find where each value ends and then convert digit characters into a number. A length-prefixed binary reader is told each field's width up front, so it reads or skips without inspecting content.

open as a page

When is a value correctly serialized, given that the reader reconstructs a new value rather than receiving the original?

level: middleimportance: must knowfreq 58%

basics

~10 s

When decoding the bytes yields a value the application cannot distinguish from the original by any observation it makes. Correctness is round-trip equality over the declared fields, not byte-identity of the two memory images.

open as a page

How does a discriminated union carry a polymorphic node's concrete type on the wire, and what may a reader do with an unknown tag?

level: seniorimportance: must knowfreq 52%

basics

~20 s

A discriminated union pairs an explicit tag field, drawn from a closed set declared in the contract, with that variant's fields. A reader meeting an unknown tag can reject the message, degrade to the shared fields, or retain the variant unchanged.

open as a page

What does schema-on-write guarantee about an archived event file that schema-on-read leaves to whoever opens it five years later?

level: seniorimportance: must knowfreq 58%

basics

~20 s

Schema-on-write checks the record against a declared schema before the bytes are stored, so everything in the archive conforms to some known version. Schema-on-read stores whatever arrived and leaves structure and validation to each consumer, years later.

open as a page

For a variable-length field inside a binary record, what changes when its length is written as a prefix rather than marked by a terminator byte?

level: middleimportance: should knowfreq 52%

basics

~20 s

A length prefix lets the reader take exactly that many bytes and step over the field without inspecting it, and the payload may hold any byte value. A terminator forces a scan and forbids that byte inside the payload unless it is escaped.

open as a page

Which parts of a node's in-memory state should be excluded from its serialized form, and how does a decoder restore them?

level: middleimportance: should knowfreq 46%

basics

~20 s

Two kinds do not travel: handles to process-local resources, which mean nothing in another process, and values derived from fields that do travel, which arrive stale. The decoder re-acquires the first and treats the second as not yet computed, recomputing on demand.

open as a page

How do inline field names, numeric tags, and purely positional fields differ in what the wire carries and what a rename costs?

level: middleimportance: should knowfreq 55%

basics

~20 s

Inline names put identity in every record, so a rename changes the bytes and breaks readers. Numeric tags carry identity in one or two bytes and leave names free to change. Positional fields carry no identity, so order becomes the contract.

open as a page

What distinction do the words serialization, marshalling and persistence carry when a team uses all three about the same value?

level: middleimportance: should knowfreq 45%

basics

~20 s

Serialization names the mechanism: a value becomes a flat byte sequence and back. Marshalling names preparing a value to cross into another execution context, which may ship a reference instead of the content. Persistence names storing it so it outlives the process.

open as a page

A service trims a UTF-8 text field so it fits a byte-length budget on the wire; what can go wrong, and why?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A length counts bytes, but a UTF-8 character takes one to four of them, so a cut at an arbitrary byte position can land inside a character. The field then carries an incomplete sequence that a strict decoder rejects outright.

open as a page

Why can a reader of purely positional schema-driven bytes not decode them with only its own current schema?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Because the bytes were laid out by the writer's schema, not the reader's. The reader's schema says what it wants; only the writer's says what is actually there, in what order and at what width, so decoding needs both.

open as a page

A high-volume internal hop uses a text encoding and the team wants a binary one purely for size — what do you check first?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Check what the hop is actually bound by. If the link is the constraint and processor headroom exists, compressing the text buys most of the size win for far less disruption; a binary encoding is justified when decode cost or skipping unwanted fields is the real constraint.

open as a page

A batch job writes a value into a queue file that a different program reads a year later; which boundary makes that hop the demanding one?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The time boundary. Crossing a process or a network leaves both ends alive and able to be diagnosed and changed together; crossing a year leaves the reader alone with immutable bytes, no writer to ask, and only whatever description of the shape was stored alongside them.

open as a page

Your teams are defining a shared in-house binary record layout; which byte-level conventions do you pin first, and what does each cost?

level: principalimportance: should knowfreq 30%

basics

~20 s

Pin four things: how integers are represented, the byte order of fixed-width fields, how every variable-length field declares its end, and the text encoding. Each one trades payload size against random access, writer complexity and how readable a hex dump stays.

open as a page

When publishing one node of a deeply linked build graph to another team, how deep should the serialized form reach?

level: principalimportance: should knowfreq 34%

basics

~20 s

Cut at the boundary of what the consumer cannot act without. Embed that subgraph as one consistent snapshot; emit stable identifiers for everything beyond it, plus the few fields needed to avoid an immediate follow-up fetch, and mark which snapshot the references were consistent with.

open as a page

You own the encoding policy for an event archive whose consumers are unknown five years out: which side of this split do you mandate, and on what grounds?

level: principalimportance: should knowfreq 35%

basics

~20 s

Mandate that anything entering long-term storage is interpretable from storage alone: either self-describing bytes, or schema-driven bytes with the writer schema in the same durable object. Decide per hop, not per estate, and defend it on asymmetry of failure.

open as a page

Why does a binary format apply ZigZag encoding to a signed integer before writing it as a varint?

level: middleimportance: nice to knowfreq 34%

basics

~20 s

Two's complement puts every negative number at the top of the unsigned range, so -1 would fill ten varint bytes. ZigZag interleaves the signs, mapping 0, -1, 1, -2 onto 0, 1, 2, 3, so small magnitudes stay short.

open as a page

A team says archived documents need no schema because field names are in the bytes; what does self-description still not supply?

level: middleimportance: nice to knowfreq 27%

basics

~20 s

Names give a reader structure, not meaning. Self-describing bytes never say which fields are required, what an absent one means, what units or which closed set of values apply, or which shapes are legal but simply rare.

open as a page

Why does embedding raw bytes inside a text-encoded message inflate the payload by about a third?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

A text message can only carry characters, so raw bytes must be re-encoded into a safe alphabet. Base64 carries six bits per character, turning every three input bytes into four characters: roughly a third larger, before padding.

open as a page

Why can an open file handle or network connection held by a value not be carried across a serialization boundary?

level: middleimportance: nice to knowfreq 32%

basics

~20 s

A handle is a token naming an entry in a table the operating system keeps for one specific process. It names a live relationship, not data, so writing its number out ships an index into a table the reader does not have.

open as a page

What must a decoder do when a reference names a node identifier whose body it has not yet read from the stream?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

It records an unresolved slot and fills it once the body arrives, either by backpatching a fixup list at the end or by decoding in two passes. Refusing forward references is impossible for a cyclic graph.

open as a page