skip to content

A lead argues that generating stubs for every language from one interface definition makes the internal contract identical everywhere. What does that actually guarantee, and where must teams still be aligned by hand?

level: principalimportance: should knowfreq 38%

answer

  1. identical bytes, not identical meaning
  2. the type system stops at the boundary
  3. units and invariants live in prose
  4. behaviour is not part of the shape
  5. who may change the definition

basics

~20 s

It guarantees identical bytes and identical field identity: any generated reader decodes what any generated writer wrote. It does not guarantee identical meaning — units, invariants, required-ness, error behaviour and ownership of the definition are agreements no schema expresses.

solid answer

~50 s

The guarantee is real but narrower than the claim. One definition compiled into every language produces readers and writers that agree on the encoding, on which field is which, and on each field's declared type — so nobody hand-writes a parser, no two teams disagree about the layout, and adding a language is a build step rather than a project. What the definition cannot carry is **semantics**: that a duration is in milliseconds, that two fields must be set together, that an empty list means "unfiltered" rather than "nothing matched", or what a caller should do when an operation half-succeeds. Those live in prose and in application code on both sides. Nor does it settle who may change the definition, or how evenly the ecosystems support it — the least-supported language in the fleet sets the practical pace. Treat the parity as a floor to build agreements on, not as the agreement.

go deeper

for a junior

Take away the boundary: generating code from one definition makes both sides agree on the bytes and on which field is which, not on what those fields mean.

for a middle

Be able to give a concrete gap — units, an emptiness convention, or an invariant spanning two fields — that the declared types cannot express and both sides must enforce themselves.

for a senior

Show where incidents come from: two type-correct systems disagreeing about meaning or failure behaviour, and the conventions and tests you put in place so that cannot happen quietly.

for a principal

Own the policy layer: who may change the definition, where it lives, which ecosystems are genuinely first-class, and which hops are deliberately exempt because their readers need human-readable payloads.

## What a shared interface definition genuinely delivers When one IDL file is the source for every language in a fleet, some things stop being negotiable, and that is worth stating plainly before qualifying it. - **Byte-level agreement.** A writer generated in any supported language emits bytes a reader generated in any other can decode. There is no per-language parser to hand-write and no per-pair integration to test for layout. - **Field identity is fixed once.** Which field is which is decided in the definition, not rediscovered by each team, so the classic cross-team disagreement about spelling, casing or ordering simply does not arise. - **Declared types are enforced at the boundary.** A field declared as an integer cannot arrive as free text; the decoder rejects bytes that do not match the declared layout. - **Adding a language is a build step.** A new team in a new ecosystem generates stubs and participates, instead of negotiating a contract from scratch. - **The definition becomes a reviewable artifact.** Contract changes show up as a diff on one file, which is an enormously better review surface than "someone changed a response body". That is a strong floor, and it is why this family is the default answer for high-volume internal traffic in polyglot organisations. ## Where the guarantee stops The failure mode of the claim is the word *identical*. What is identical is the **wire**, not the **system**. A lead is expected to know the gap and to plan for it. | the claim | what is actually guaranteed | what remains a human agreement | |---|---|---| | "the contract is identical" | the encoding and field identity | the meaning of each field | | "types are enforced" | declared types at the boundary | units, ranges, invariants across fields | | "every language behaves the same" | every language decodes the same bytes | the shape and ergonomics of each generated API | | "the schema is the contract" | the data's shape | failure behaviour, retries, idempotency | The items in the right-hand column are where production incidents actually come from: 1. **Units and ranges.** Nothing in a definition says a timeout is milliseconds rather than seconds, or that a discount is a fraction rather than a percentage. A type-correct message can still be catastrophically wrong. 2. **Cross-field invariants.** "Exactly one of these three may be set", "if this is present that must be too" — a schema of independent fields cannot express these, so both sides must enforce them in application code, and they will drift unless the rule is written down and tested. 3. **Meaning of emptiness.** Whether an empty collection means "no results" or "no filter applied" is a semantic decision carried entirely in prose. 4. **Behaviour, not data.** Whether an operation may be retried safely, what partial success looks like, which failures are the caller's fault — none of this is in the data's shape, and it is where most cross-team misunderstanding lives. 5. **Ergonomic divergence.** The generated API in each ecosystem follows that ecosystem's conventions, so code reading the same field looks different from language to language. That is fine, but it means "the same contract" does not mean "the same code", and reviewers moving between languages should expect it. ## The organisational questions the tooling does not answer A principal-level answer goes past the technical gap to the ownership one. - **Who may change the definition?** Field identity is permanent in this family, so the ability to add or retire a field is the ability to bind every consumer forever. That needs a named owner and a review path, which is a policy decision, not a tooling one. - **Where does the definition live?** One shared repository, per-service repositories, or a published artifact per consumer — each choice trades discoverability against coupling, and each has a different failure mode when a change lands. - **Which ecosystems are actually first-class?** Support is uneven across languages in practice. The least-supported language in the fleet determines what the organisation can really rely on, and a lead should know which one that is before making the encoding a mandate. - **What is the escape hatch?** Some hops genuinely want human-readable payloads — a public edge, a debugging endpoint, a low-volume administrative tool. Mandating one encoding everywhere converts a good default into a tax. ## How to frame the answer The defensible position is: adopt the shared definition for the parity it really gives — one encoder, one decoder, one reviewable contract artifact, no hand-written parsers — and then be explicit that semantics, failure behaviour and ownership are *separate* agreements that the definition carries comments about at best. Teams that believe the schema is the whole contract discover the gap during an incident, when two type-correct systems disagree about what a field meant.

  • Give a concrete way two type-correct services can still disagree.
    One writes a timeout field as seconds and the other reads it as milliseconds. Both satisfy the declared integer type, both encode and decode without error, and the effect is a thousandfold difference in behaviour that no decoder can catch. Only a naming convention, a documented unit or a wrapper type agreed by both sides prevents it.
  • Why does the least-supported language in a fleet constrain the decision?
    Support quality is uneven across ecosystems, and a fleet-wide mandate is only as strong as its weakest generated toolchain. If one team's language has thin or lagging support, that team either carries extra maintenance or quietly deviates, so a lead should check the weakest link before making the encoding a standard.
  • Should every hop in an organisation use this encoding once it is adopted?
    No. It earns its cost on high-volume internal links between services that deploy together. Low-volume administrative endpoints, human-facing debugging surfaces and boundaries crossed by parties who do not hold the definitions are usually better served by a readable payload, and mandating one encoding everywhere turns a good default into overhead.

saying these in an interview costs you the question

  • Believes generated stubs make two services semantically compatible
  • Thinks declared types can express cross-field invariants
  • Assumes every ecosystem supports the encoding equally well
  • Treats the definition as the whole contract, behaviour included
  • Leaves ownership of the definition unassigned across teams
  • Mandates one encoding for every hop regardless of readership