# Plan a vertical feature slice before frontend and backend diverge

> Agree on states, payload examples, validation, errors, observability, and rollout for one end-to-end slice before parallel implementation drifts.

Canonical URL: https://www.devobs.io/articles/frontend-backend-contract-slice/
By: Claire Dubois
Published: 2024-10-18T08:22:16.204Z
Updated: 2026-09-06T08:31:04.426Z
Section: Architecture

Before frontend and backend engineers implement a feature in parallel, agree on one thin vertical slice that can be exercised end to end. The contract should describe user-visible states, representative requests and responses, validation ownership, stable errors, observability, and rollout. It should leave component internals local to each team.

Reviewed: 2026-09-06.

## Start with behavior, then describe the wire

Use a concrete journey: “A workspace administrator invites one member.” List initial, loading, success, empty, retryable failure, permanent failure, and concurrent-change states. Decide what the user sees and which action remains possible in each state. This prevents the API from returning a technically valid response the interface cannot explain.

Then write examples. A request might contain an email, role, and [idempotency key](https://www.devobs.io/articles/idempotency-keys-as-an-api-contract/). The success response should identify the invitation and its state. Define whether creation is synchronous, what duplicate submission means, and how the client polls or subscribes if processing continues. Examples expose naming and nullability disagreements earlier than generated types do.

Use an OpenAPI document as the HTTP contract. The [OpenAPI Specification](https://spec.openapis.org/oas/latest.html) defines a standard, language-agnostic interface to HTTP APIs and can describe operations, parameters, request bodies, responses, and reusable schemas. Keep examples alongside schemas and review the rendered change as a product change. The contract belongs to the service that enforces it, while both teams approve breaking semantics.

## Divide validation by authority

The browser validates for immediate interaction: required fields, obvious format, and local constraints. The API repeats all security and domain validation because clients are untrusted. The database protects storage invariants such as uniqueness and references. Map failures back through a stable response rather than copying a database message into the UI.

[JSON Schema 2020-12 core](https://json-schema.org/draft/2020-12/json-schema-core) defines core terminology and mechanisms, and JSON Schema uses vocabularies of keywords to describe and constrain JSON documents. Schema validation can align shapes and simple constraints, but it cannot replace business rules that depend on current state, authorization, or multiple records. Document those rules in operation behavior and tests.

Define an error envelope with a stable code, safe message, correlation ID, and optional field pointers. For example, `INVITATION_ALREADY_PENDING` is actionable; `409` alone is not. Decide which codes the UI handles specially and what its fallback does with an unknown future code. Never make display logic depend on English message text.

## Agree on concurrency and partial state

The invitation may be revoked between list and submit. Choose optimistic concurrency, idempotent semantics, or explicit conflict behavior. If the backend accepts an idempotency key, define its scope, retention, and response when the same key arrives with different input. If a list response can be stale, say which subsequent action is authoritative.

Loading and empty are separate states. A blank table before the request completes should not tell the user there are no invitations. Similarly, partial data needs an explicit contract: which fields may be unavailable, how freshness is represented, and whether the UI may act on stale values.

## Add checkpoints that test the seam

Before coding, commit examples and generate a mock or fixture both sides can run. During implementation, run provider contract tests against the real handler and consumer tests against recorded examples. At integration, trace one request with the same correlation ID through UI, API, and background work.

Roll out behind a capability or version the old client can ignore. Dashboards should show request outcome by stable error code, latency, and the user journey's completion rate without high-cardinality personal data. Define [rollback compatibility](https://www.devobs.io/articles/rollback-compatible-release-design/): can the new frontend talk to the old backend and vice versa?

Use this checklist for the first slice: user states, three payload examples, authoritative validation, error codes, concurrency rule, idempotency, correlation, rollout, and compatibility. Schedule a 30-minute contract review around the invitation example, then make both teams demonstrate the same happy path and one conflict before expanding the feature.

## Source references

- <https://spec.openapis.org/oas/latest.html>
- <https://json-schema.org/draft/2020-12/json-schema-core>
