OOP & Design Principles • Abstraction & EncapsulationMedium⏱️ ~2 min
Contract Design: SLOs, Semantics, and Compatibility
Effective abstractions require contracts that go far beyond method signatures. A production grade interface specifies behavioral semantics including idempotency guarantees, consistency models (strong, eventual, read your writes), ordering promises, and failure behavior like timeout values and retry policies. Service Level Objectives become first class parts of the contract: publishing targets like 50 milliseconds p50, 200 milliseconds p95, and 0.1% error rate sets clear expectations and enables downstream teams to budget their own latency.
Compatibility management determines whether your abstraction scales over time. Prefer additive schema evolution where new fields can be safely ignored by old clients, stable numeric identifiers never get repurposed, and breaking changes require explicit new versions. Amazon's API review process gates changes that might leak invariants, while Google's IDL tooling enforces forward and backward compatible evolution. Meta uses centralized schema governance with Thrift and GraphQL, running automated compatibility checks before deployment to catch drift early.
The expand contract pattern enables zero downtime evolution. First, expand: deploy code that writes both old and new formats and reads both, preferring new. Once all producers and consumers are upgraded, contract: remove support for the old format. This requires maintaining a compatibility matrix and performing consumer driven contract tests where downstream teams lock their expectations and you catch breaking changes pre deploy.
Failure mode: Hyrum's Law states that with enough users, every observable behavior will be depended upon, regardless of documentation. Clients may rely on error message text, response ordering, or default timeout values. Internal optimizations that preserve the formal API can still break these undocumented dependencies, causing outages during what seemed like safe refactors.
💡 Key Takeaways
•Contracts must specify idempotency, consistency models, ordering guarantees, pagination behavior, and explicit failure semantics including timeout values and retry policies, not just method signatures
•Service Level Objectives are first class contract elements: publish concrete targets like 50 milliseconds p50, 200 milliseconds p95, and 0.1% error rate to enable downstream latency budgeting
•Additive schema evolution enables compatibility: allow unknown fields to be ignored, reserve stable numeric identifiers, and never repurpose fields to avoid breaking existing clients
•The expand contract pattern supports zero downtime evolution: write both old and new formats during transition, read both preferring new, then remove old support only after all clients upgrade
•Consumer driven contract tests lock downstream expectations and catch breaking changes before deployment, maintaining a compatibility matrix across service versions
•Hyrum's Law guarantees that clients depend on undocumented behaviors like error message text or response ordering; internal optimizations can break these implicit contracts even when the formal API is unchanged
📌 Examples
Amazon S3 evolved from eventually consistent to read after write consistency for all operations by 2020, requiring careful contract updates since applications built on old semantics assumed they might read stale data after writes
Google's Protocol Buffers enforce compatibility through field numbering: each field gets a permanent numeric ID, new fields must use new numbers, and parsers skip unknown fields, enabling old clients to work with new servers
Meta's Thrift services maintain compatibility matrices showing which client versions work with which server versions, running automated tests against each combination before releasing breaking changes behind explicit version flags