Contract Review Playbook: How Senior Engineers Review API, Event, and Schema Changes
Learn Java API Contract Engineering, Event Contract Engineering & Schema Governance - Part 025
Contract review playbook for senior Java engineers: API contract review, event contract review, schema review, compatibility review, security review, consumer ergonomics, and decision quality.
Part 025 — Contract Review Playbook: How Senior Engineers Review API, Event, and Schema Changes
Tujuan Pembelajaran
Contract review adalah salah satu tempat paling jelas terlihat perbedaan antara engineer biasa dan engineer top-tier.
Engineer biasa review contract dengan bertanya:
Apakah schema valid?
Apakah endpoint jalan?
Apakah field-nya lengkap?
Senior engineer yang kuat bertanya:
Apa promise yang sedang dibuat?
Siapa consumer-nya?
Apa invariants-nya?
Apa yang akan rusak dalam 6 bulan?
Apa semantic ambiguity-nya?
Apa compatibility surface-nya?
Apa migration path-nya?
Apa observability dan rollback-nya?
Apa evidence bahwa ini aman?
Part ini adalah playbook praktis untuk mereview:
- OpenAPI/HTTP API contract;
- AsyncAPI/event contract;
- Avro/Protobuf/JSON Schema;
- Kafka topic/key/retention contract;
- SDK/generated client impact;
- compatibility and lifecycle changes;
- security/data classification;
- governance metadata;
- migration/deprecation;
- operational readiness.
Setelah part ini, kamu harus mampu melakukan contract review seperti platform engineer senior: tajam, efisien, evidence-based, dan tidak sekadar nitpick naming.
1. Contract Review Mindset
Contract review bukan taste review. Bukan juga sekadar YAML review.
Contract review bertujuan memastikan:
- contract menyatakan promise yang benar;
- consumer bisa memakai contract tanpa meeting tambahan;
- provider bisa mengimplementasikan dan mengoperasikan contract;
- evolution path aman;
- failure behavior jelas;
- security/data governance aman;
- generated tooling tidak menciptakan surprise;
- observability dan support cukup;
- breaking/dangerous changes dikendalikan;
- keputusan terekam.
Review yang baik bukan mencari kesalahan sebanyak mungkin. Review yang baik menurunkan risiko terbesar dengan feedback paling actionable.
2. Review Layers
Gunakan layered review agar tidak tenggelam di detail.
| Layer | Pertanyaan utama |
|---|---|
| Intent | Masalah apa yang diselesaikan? |
| Semantics | Apa arti contract ini? |
| Surface | Apa public promise-nya? |
| Compatibility | Apa yang berubah dan siapa terdampak? |
| Consumer ergonomics | Apakah mudah dipakai dengan benar? |
| Failure | Bagaimana error/retry/DLQ/replay? |
| Security/data | Apakah data boleh mengalir ke sini? |
| Operational | Apakah topic/key/retention/SLO jelas? |
| Tooling | Apakah generator/validator/registry bisa mendukung? |
| Governance | Apakah owner, lifecycle, changelog, CDR ada? |
Review dari atas ke bawah. Jangan mulai dari indentation kalau semantics belum jelas.
3. Fast Triage: 10-Minute First Pass
Dalam 10 menit pertama, cari risiko besar:
- apakah ini safe/dangerous/breaking/semantic breaking?
- apakah owner jelas?
- apakah lifecycle jelas?
- apakah consumer diketahui?
- apakah ada migration plan jika perlu?
- apakah schema valid dan lint passing?
- apakah ada examples?
- apakah security/data classification jelas?
- apakah generated code impact disebut?
- apakah runtime operational behavior berubah?
Jika salah satu high-risk item kosong, review harus berhenti di situ dulu.
4. Contract PR Description Template
Minta author mengisi ini sebelum review:
## What changed?
Describe contract change in human language.
## Why?
Business/platform reason.
## Artifact(s)
- OpenAPI:
- AsyncAPI:
- Schema:
- Topic:
- SDK:
## Compatibility classification
Safe / Dangerous / Breaking / Semantic breaking.
## Consumers impacted
Known consumers and risk.
## Migration plan
Required only for dangerous/breaking changes.
## Runtime/operational impact
Topic/key/retention/error/retry/auth/rate limit/etc.
## Security/data impact
Classification/PII/access/retention.
## Tests and evidence
- schema validation
- compatibility check
- generated client compile
- provider tests
- consumer tests
- replay tests
If PR lacks context, reviewers waste time reverse-engineering intent.
5. API Contract Review
5.1 Resource and Operation Semantics
Ask:
- Is the resource noun meaningful?
- Is HTTP method appropriate?
- Is operation id stable?
- Is request/response semantic clear?
- Are state transitions explicit?
- Is idempotency documented?
- Are conditional updates needed?
- Is pagination/filter/sort specified?
- Are partial updates semantics clear?
- Are examples realistic?
Bad endpoint:
POST /customers/{id}/process
Ask:
- process what?
- is it command?
- what state changes?
- what errors?
- is it idempotent?
Better:
POST /customers/{customerId}/kyc-verifications
or:
POST /cases/{caseId}:approve
depending API style.
5.2 Request Body Review
Checklist:
- Are required fields truly required from day one?
- Are optional fields defaulted clearly?
- Are null and absent semantics clear?
- Are field names domain-specific?
- Are validation constraints too strict?
- Is money/time modeled safely?
- Is ID format future-proof?
- Is
additionalPropertiespolicy clear? - Are examples valid?
- Is sensitive data minimized?
Danger sign:
{
"data": {},
"status": "A",
"type": "1"
}
Review comment:
`data`, `status`, and `type` are ambiguous. Please split into named fields with documented meanings. If status uses coded values, define enum semantics or use descriptive values.
5.3 Response Body Review
Ask:
- Are response fields stable public promise?
- Are internal entity fields leaking?
- Are computed fields clearly documented?
- Are timestamps named by semantics?
- Are status fields overloaded?
- Are enums open or closed?
- Is pagination wrapper consistent?
- Are links/metadata needed?
- Are deprecated fields marked?
- Are examples complete?
5.4 HTTP Status and Error Review
Require:
- success status correct;
- validation error documented;
- business rejection documented;
- conflict/precondition documented;
- authn/authz documented;
- rate limit documented if applicable;
- retryability visible;
- error code stable;
- correlation/request ID included;
- no raw exception leakage.
Bad:
responses:
'500':
description: Error
Better:
'422':
description: Customer is not eligible for requested action.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
5.5 API Compatibility Review
Ask:
- Was a field removed?
- Was a field renamed?
- Was a type changed?
- Was validation tightened?
- Was a required request field added?
- Was default behavior changed?
- Was operationId changed?
- Was response status changed?
- Was error code/retryability changed?
- Was auth scope changed?
If yes, require classification and plan.
6. Event Contract Review
6.1 Is It Really an Event?
Ask:
- Is name past tense?
- Did something already happen?
- Who is authority?
- Is producer allowed to state this fact?
- Is this actually a command?
- Is it notification or state transfer?
- Is event consumer-specific?
- Does event name tell the truth?
- Can it be replayed?
- What may consumer assume?
Bad:
SendCustomerToCRM
Review:
This is consumer-specific and command-like. Please model the domain fact (`CustomerRegistered`, `CustomerProfileUpdated`) and let CRM consume it, unless this is intentionally a targeted command channel.
6.2 Event Name Review
Good names:
CaseApproved
PaymentCaptured
CustomerRegistered
KycVerificationRejected
PolicyRuleActivated
Bad names:
CustomerUpdated
DataChanged
ProcessDone
EventMessage
Review questions:
- What changed exactly?
- Is field-level change domain-significant?
- Would different consumers react differently?
- Should there be separate events?
6.3 Event Payload Review
Checklist:
- Does payload include enough stable facts?
- Does it avoid dumping internal entity?
- Does it avoid consumer-specific fields?
- Is sensitive data minimized?
- Are previous/new values included if transition matters?
- Are reason codes stable?
- Are IDs stable?
- Are time fields explicit?
- Are enum values open/closed?
- Are null/default semantics clear?
- Are examples realistic?
6.4 Event Envelope Review
Require:
- eventId;
- eventType;
- source;
- occurredAt;
- schemaRef;
- correlationId where applicable;
- causationId where applicable;
- aggregateId/version for stateful events;
- tenant/jurisdiction if relevant;
- data classification.
Review comment example:
This event lacks `aggregateVersion`. Because consumers build projections and ordering is per case, we need a monotonic case version so consumers can detect gaps, duplicates, and out-of-order delivery.
6.5 Kafka Review
Ask:
- What topic?
- What key?
- Why this key?
- What ordering guarantee?
- What retention?
- Is compaction enabled?
- Are tombstones used?
- Is replay supported?
- Is DLQ/quarantine defined?
- Are unknown event types tolerated?
Bad:
topic: events
key: eventId
for case lifecycle events.
Comment:
If consumers need per-case ordering, key should be caseId/aggregateId, not eventId. eventId distributes well but destroys per-case ordering.
7. Schema Review
7.1 Avro Review
Checklist:
- record name/namespace stable?
- added fields have defaults?
- nullable unions use
["null", T]with default null? - logical types used for timestamps/date/decimal?
- enum addition reviewed?
- aliases honest?
- namespace not tied to implementation?
- generated Java impact checked?
- registry compatibility mode appropriate?
- old fixtures tested?
Review comment:
This adds `approvalChannel` without a default. New readers will fail when replaying old events. Please add a default or make the migration explicit with a new event type.
7.2 Protobuf Review
Checklist:
- no field number reuse?
- removed fields reserved?
- removed names reserved?
- zero enum value unspecified?
- enum additions reviewed?
- presence modeled correctly?
- oneof changes reviewed?
- package/java_package stable?
- generated Java source compatibility checked?
- service method changes reviewed?
Review comment:
Field number 7 was previously `legacy_status`. Reusing it for `risk_band` is unsafe. Please reserve 7 and allocate a new field number.
7.3 JSON Schema Review
Checklist:
$schemapresent?$idstable?requiredcorrect?- null vs absent clear?
additionalPropertiesexplicit?formatenforcement known?oneOfhas discriminator?- constraints not overly tight?
- defaults not assumed to mutate data?
- compatibility direction considered?
Review comment:
`default: 50` does not mean the validator will insert pageSize. Please document provider defaulting behavior explicitly and test it.
8. Compatibility Review
8.1 Change Classification
Reviewer should force a classification:
Safe / Dangerous / Breaking / Semantic breaking
Do not accept:
minor change
without explanation.
8.2 Questions
- Can old consumers read new data?
- Can new consumers replay old data?
- Does semantic meaning remain true?
- Does generated Java compile for old consumer?
- Does API SDK public surface change?
- Did topic/key/retention change?
- Did error retryability change?
- Did security classification change?
- Are examples updated?
- Is migration observable?
8.3 Red Flags
- “No consumers depend on this” without inventory.
- “Internal API, so breaking is okay.”
- “Schema registry passed.”
- “Deprecated means we can remove.”
- “This field is optional but all consumers should use it.”
- “We changed status meaning but name stays same.”
- “Only key changed, payload same.”
9. Security and Data Review
Contract reviewers should not leave security only to security team.
Ask:
- Does contract expose PII?
- Is data classification correct?
- Are existing consumers authorized?
- Does DLQ preserve sensitive payload?
- Is retention compliant?
- Are error details safe?
- Are IDs guessable?
- Are tenant/jurisdiction boundaries explicit?
- Are scopes/permissions documented?
- Are examples using fake data?
9.1 Additive Field Can Be Unsafe
Adding field:
{
"nationalId": "..."
}
to a broad event is structurally additive but security-breaking.
Review comment:
This additive field changes data classification and consumer authorization requirements. Please either remove it, create a restricted event/topic, or complete data governance review.
10. Consumer Ergonomics Review
A contract can be technically correct but hard to use.
Ask:
- Is common path easy?
- Are errors machine-readable?
- Are examples realistic?
- Is pagination safe?
- Is idempotency supported?
- Are enums/unknown values handled?
- Is SDK/generated client stable?
- Are nullable fields confusing?
- Are field names domain-friendly?
- Is migration guide actionable?
Bad:
{
"result": "N",
"reason": "01"
}
Better:
{
"eligible": false,
"reasonCode": "KYC_NOT_VERIFIED"
}
11. Operational Readiness Review
For APIs:
- rate limit?
- timeout?
- cache semantics?
- idempotency?
- retryability?
- correlation ID?
- error SLO?
- graceful deprecation?
For events:
- topic/key?
- ordering?
- retention?
- replay?
- DLQ?
- consumer lag?
- poison messages?
- duplicate delivery?
- schema registry availability?
- outbox/transactional publishing?
Review comment:
The event is used by projection consumers, but retention is not documented. Please define replay window and whether an archive/backfill exists beyond Kafka retention.
12. Documentation and Examples Review
Require examples for:
- happy path;
- validation error;
- business rejection;
- conflict/precondition;
- deprecated field if present;
- event old/new version;
- DLQ message;
- replay marker if used;
- unknown enum handling if relevant.
Examples must validate against schema.
Bad example:
{
"customerId": "string",
"status": "string"
}
Good:
{
"customerId": "cus_01J2T7Q7BSM8PV8K4J6JYQH7TR",
"lifecycleStatus": "ACTIVE"
}
13. Review Comment Style
Good review comment is:
- specific;
- risk-based;
- explains why;
- suggests fix;
- separates blocker vs suggestion.
Bad:
Bad naming.
Good:
Blocker: `CustomerUpdated` is too generic for a stable integration event. Consumers cannot know whether this represents lifecycle, profile, KYC, or access change. Please either split into domain-specific events or document this as notification-only with `resourceUrl` and no projection guarantees.
13.1 Prefix Comments
Use:
Blocker:Risk:Question:Suggestion:Nit:
This improves review efficiency.
14. Review Decision
Possible outcomes:
| Decision | Meaning |
|---|---|
| Approve | safe enough, evidence sufficient |
| Approve with conditions | must complete listed actions before release |
| Request changes | risks must be fixed |
| Escalate | requires architecture/security/domain review |
| Reject | contract direction is fundamentally wrong |
Do not approve dangerous change because “team needs to ship” without recording exception.
15. Contract Review Checklist: API
apiReview:
semantics:
- resource meaningful
- method appropriate
- operationId stable
- idempotency documented
request:
- required fields justified
- null/absent clear
- validation constraints safe
- examples valid
response:
- no entity leakage
- timestamps semantic
- enums open/closed documented
- pagination/filter/sort clear
errors:
- problem schema
- stable error codes
- retryability
- correlation id
compatibility:
- diff classified
- generated client impact checked
- changelog updated
security:
- scopes
- classification
- sensitive fields
governance:
- owner
- lifecycle
- CDR if dangerous
16. Contract Review Checklist: Event
eventReview:
classification:
- event_not_command
- fact_past_tense
- authority_clear
envelope:
- eventId
- eventType
- source
- occurredAt
- schemaRef
- correlationId
- aggregateId
- aggregateVersion
payload:
- stable_facts
- no_entity_dump
- enough_for_consumers
- sensitive_data_minimized
kafka:
- topic
- key
- ordering
- retention
- replay
- dlq
compatibility:
- schema_registry
- semantic_review
- old_fixtures
- generated_code
governance:
- owner
- lifecycle
- examples
- data_classification
17. Contract Review Checklist: Schema
schemaReview:
identity:
- name_stable
- namespace_package_stable
- schema_id_or_subject
structure:
- required_optional_correct
- defaults_correct
- nullability_clear
- constraints_future_safe
evolution:
- compatibility_mode
- old_versions_tested
- aliases_or_reserved_fields
- enum_strategy
java:
- generated_code_compile
- package_stability
- public_api_impact
governance:
- owner
- lifecycle
- changelog
- examples
18. Contract Review Anti-Patterns
18.1 YAML Formatting Review Only
Misses semantic breaks.
18.2 Rubber Stamp
All PRs approved because author is senior.
18.3 Review Board for Every Safe Change
Creates bottleneck and bypass culture.
18.4 Tool Output Blindness
Reviewer trusts schema compatibility pass without reading meaning.
18.5 Consumer-Blind Review
No consumer impact considered.
18.6 No Migration Demand
Breaking change approved with no migration guide.
18.7 Security Late Review
Sensitive field added, security only notices after production.
18.8 Review Without Examples
Contract accepted but consumers cannot learn.
18.9 No Decision Records
Rationale lost.
18.10 Nitpick Over Risk
Reviewer blocks style but misses key/retention change.
19. Practice Lab
Lab 1 — Review Bad API
Review:
POST /customer/process
Body:
{
"id": "123",
"status": "A",
"data": {}
}
Write review comments.
Lab 2 — Review Bad Event
Review event:
{
"eventType": "CustomerUpdated",
"customerId": "cus_123",
"status": "A",
"timestamp": "2026-06-29T05:00:00Z"
}
Identify issues and propose replacement.
Lab 3 — Review Avro Change
Old Avro schema has:
{ "name": "caseId", "type": "string" }
New schema adds:
{ "name": "approvalChannel", "type": "string" }
No default. Write review.
Lab 4 — Review Protobuf Change
Old:
string email_address = 4;
New:
string national_id = 4;
Write review.
Lab 5 — Review Kafka Change
Topic key changes from caseId to eventId. Payload unchanged. Classify and write comment.
Lab 6 — Review Security Change
Event adds optional nationalId field to broad customer-events. Write review.
20. Senior Engineer Heuristics
- Review meaning before syntax.
- Every contract change creates or changes a promise.
- Names are compatibility surface.
- Unknown consumers require conservative design.
- Schema validity is not enough.
- Event authority must be clear.
- Kafka key is not implementation detail.
- Generated Java impact matters.
- Examples reveal ambiguity faster than descriptions.
- Security review starts at contract design, not after implementation.
- Deprecation requires migration evidence.
- A good review comment explains risk and fix.
- Block semantic breaks, not harmless formatting.
- Risk-based review keeps governance fast and meaningful.
- A contract that needs a meeting to understand is not ready.
21. Summary
Contract review is an engineering practice for protecting consumers, providers, and long-term system evolution. Strong reviewers look beyond schema syntax into semantics, compatibility, consumer ergonomics, operational behavior, security, lifecycle, and evidence.
Main takeaways:
- review intent and semantics first;
- classify changes explicitly;
- require examples, tests, lifecycle, and owner;
- review API errors and event failures as first-class contract;
- review Kafka topic/key/retention as contract surface;
- review generated Java impact;
- review data classification and security implications;
- demand migration plan for dangerous/breaking changes;
- write actionable review comments;
- use risk-based approval, not rubber stamp or bureaucracy.
Part berikutnya membahas contract governance automation: linting, diffing, policy-as-code, CI gates, registry hooks, catalog sync, generated code checks, and automated risk classification.
You just completed lesson 25 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.