Protocol-first design
What is Protocol-first
Protocol-first is an approach in which an interaction contract between components (services, customers, external partners) is designed and fixed before implementation. Code, storage, infrastructure and documentation are subject to the contract and are automatically generated from it, and not vice versa.
Unlike code-first, where the API is only a byproduct of code, Protocol-first makes the protocol a primary artifact: it owns domain concepts, data models, statuses, errors, idempotency semantics, SLO/SLI, and even version policy.
Why do you need it?
Consistency and predictability of interfaces across the organization.
Fast onboarding (SDK/stable/client autogeneration, uniform errors and codes).
Reliable evolution (compatibility of schemes, test contracts, clear version policy).
Product Focus: Discuss behavior, SLA and UX integration prior to code writing.
Automation: CI/CD collects artifacts (clients, server stubs, validators) from a single source of truth.
Security and compliance: rights, PII masking, retention policies are enshrined in the contract.
Core approach
1. Single Source of Truth (SSOT) - machine-readable specifications:
REST: OpenAPI/JSON Schema.
Events and streaming: AsyncAPI, Avro/JSON Schema.
RPC: Protobuf (gRPC), Thrift, Smithy.
GraphQL: SDL + directives/policies.
2. Pre-implementation arrangements: domain glossary, error codes, idempotency semantics, deadlines, retrays, deduplication.
3. Autogeneration: clients/server stubs, types, SDKs, test contracts, moks, Postman collections, Terraform/OpenAPI Gateway config.
4. Governance: linters/policies (naming, pagination, filters, errors), review via API guild, change-advisory for major versions.
5. Compatibility: strict verification of "additive-only" diffuses, semantic versioning, canary/consumer-driven tests.
6. Observability at the contract level: correlation IDs, error models, delay budgets are spelled out in the protocol.
What the process looks like (skeleton)
1. Initiation: product brief → user journeys → API/Protocol PRD (resources/methods/events, SLA/SLO, errors, limits).
2. Modeling: draft specification (OpenAPI/AsyncAPI/Proto) + data schemas, dictionary of terms.
3. Contracts and UX integrations: payload examples, error contracts, status maps, versioning rules.
4. Review and governance: linters/standards, discussion of domain invariants, lock-in MGC (minimum warranty contract).
5. Auto-generation of artifacts: SDKs, stabs, test fixes, infrastructure stubs (Gateways, IAM scopes).
6. Implementation and Contract Tests: Supplier and consumers undergo compatibility checks in CI.
7. Observability and SLO: correlation-id tracing, error catalog, retray/timeout budgets.
8. Releases and evolution: additive-first, rejection policy, canary, A/B capability flags.
Interaction protocols and styles
REST/HTTP
Standards: resource model, 'GET/POST/PATCH/DELETE', pagination (cursor), filters, sorting.
Fields and schemes: JSON Schema, formats ('date-time', 'uuid'), invariants (regex/enum/min-max).
Errors: single format ('type', 'code', 'title', 'detail', 'trace _ id'), mapping to HTTP stacks.
Change control: ETag/If-Match, idempotent keys for POST, explicit semantics 409/422.
gRPC/RPC
Protobuf: stable tag numbering, 'optional', disallowing reuse of deleted fields.
Deadlines and priorities in the contract; stable statuses (OK, INVALID_ARGUMENT, FAILED_PRECONDITION, etc.).
Streaming: message order specification, backpressure, final trailers.
Event-driven (Kafka/NATS/SNS/SQS)
AsyncAPI: themes/channels, partitioning keys, deduplication key conventions, retentions, exactly-once semantics "vs" at least once. "
Core event and enrichment: separate minimal payload and extensions; version 'event _ type '/' schema _ version'.
Idempotency: 'event _ id', 'producer _ id', policy on retrays and deduplication.
GraphQL
SDL as a contract, directives for deprecate, limits on depth and complexity, error codes/extensions contract.
Integration with architectural principles
Inverse Pyramid/Critical Path First: in the specification, highlight MGC (mandatory minimum), extensions - through '? include = '/capabilities.
Paved Roads: a set of ready-made specification templates (payment, KYC, audit, search, files) + linters.
API Gateways & Service Mesh: contract-based policies (rate-limits, auth scopes, retries, circuit-breakers).
Versioning and Evolution
Semantic Versioning:- Minor = additive fields/channels only.
- Major = breaking changes (deletions, renaming, changing semantics).
- Rejection Policy: support windows, 'Sunset' headers, notification events.
- Consumer-Driven Contracts (CDC): Verifying that the current API satisfies specific consumers.
- Schema directory: Schema Registry/Artifact Registry with history and compatibility rules (BACKWARD/FORWARD/FULL).
Safety and compliance
Authentication/authorization as part of the contract (OAuth2/OIDC scopes, mTLS, JWT claims).
PII/PCI: masking, tokenization formats, fields with special storage modes/TTL.
Audit policies: required attributes ('actor', 'subject', 'action', 'occurred _ at', 'trace _ id').
Limits: rate limit headers, quotas, message sizes, deadlines.
Contract Observability
Correlation/Request-ID: required in specification.
Error Catalog - fixed list of codes and SLAs to resolve.
SLI/SLO: p50/p95 latency, proportion of successful responses, proportion of compatible events, proportion of idempotent repeats.
Testing and quality
Contract tests (provider ↔ consumer), schema diff in CI, generation of mock servers.
Golden samples: reference examples of requests/responses, fixtures for e2e.
Chaos/latency injection: timeout/retray check, degradation of extensions when saving MGC.
Sample Domain Templates
Payment (REST + Events)
'POST/payments' → '201 Created' with 'payment _ id', 'status = authorized'.
Event 'payment. authorized. v1` (ядро): `{ payment_id, amount, currency, method, occurred_at }`.
Extension 'payment. enriched. v1 ': risk rate, geo, device-fingerprint.
Errors: '422' (validation), '402' (payment required), '409' (duplicate).
SLA: authorization ≤ 800ms p95; kernel event ≤ 2c lag p95.
KYC (gRPC + queues)
RPC `StartVerification(user_id)` → `operation_id`.
Progress events in the topic'kyc. status. v1` (`PENDING` → `APPROVED/REJECTED`).
The contract stipulates PII fields, shelf life, masking, causal failure codes.
Audit (Event-only)
`audit. recorded. v1` (ядро): `actor`, `subject`, `action`, `occurred_at`, `trace_id`.
Enrichment: IP, device, geo - a separate event/thread, does not block the kernel.
Tools and automation (approximate stack)
Спеки: OpenAPI/AsyncAPI/Protobuf/Avro/GraphQL SDL.
Линтеры: Spectral, OpenAPI Diff, Buf (protobuf), Confluent SR compatibility checks.
Генерация: OpenAPI Generator, Buf/Protoc, GraphQL Codegen, AsyncAPI Generator.
Gateway: Kong/Apigee/Azure/GCP GW, Envoy.
Тесты: Pact/CDC, Dredd, Schemathesis, Hoverfly, MockServer.
Register: Git-directory of schemes + Schema Registry/Artifact Registry.
Documentation: Redocly/Stoplight/Swagger-UI/GraphiQL/Explorer.
Anti-patterns
Code-first by accident: "MVP first on controllers," post-factual specification, discrepancy between documentation and behavior.
Swagger-wash: a formal OpenAPI without real rules (errors, limits, SLAs, versions).
Compatibility break: removed field/changed type without major version; reusing protobuf tags.
"Thick" response without pagination/filters; lack of idempotency.
Off-contract security: auth/Scopes are described in the wiki, but not in the specification.
Relationship to process organization
API Guild: standards trustees, change reviews, training.
Design Docs: for each API - PRD, ADR (solutions), SLA, risk matrix.
Change Management: RFC process, release notes, migration guides, deviation-timeline.
Paved Road & Templates: service framework generators from the specification (handler skeleton, validation, logging).
Checklists
Before starting
- There is a PRD and a domain glossary.
- Selected style (REST/gRPC/Event/GraphQL) and schema format.
- MGCs, errors, SLA/SLOs, idempotency rules defined.
Under development
- Specification passes linters and review.
- SDK/Stable/Fixture auto-generation is configured.
- Contract-tests (CDC) are included in the CI; schema-diff blocks incompatible changes.
Before Release
- Integrator documentation with examples and error codes.
- Contractually observable: correlation-id, error catalog, SLI dashboards.
- Versioning policy and deprecation are declared.
FAQ
How does Protocol-first differ from API-first?
Often terms are used interchangeably. In this article under Protocol-first, we emphasize the rigor of the contract and the coverage of all styles (REST/RPC/Events/GraphQL), including SLA, safety and observability.
Will this slow down development?
The start may be a little longer, but then we win on integrations, stability and parallel development speeds (auto-generation, stable SDKs).
What to do with quick experiments?
Use "draft" versions of schemes (draft), feature flags and sandboxes, but do not skip linters and basic compatibility rules.
Total
Protocol-first design makes the contract the center of architecture: we coordinate behavior, fix schemes, automate generation and tests, evolve additively. As a result, we get predictable integrations, high speed of development and resistance of systems to changes in scale and command.