← Back to principles
API
Validate at the Boundary
What this means in practice
Treat every integration boundary as untrusted and observable.
Validate all external inputs and downstream responses against explicit schemas, and fail in controlled ways when the data you depend on changes.
Capture enough structured information at the boundary to make triage straightforward, and build resilience into integrations through timeouts, retries, circuit breakers, and kill switches.
Why this matters
External systems change, fail, and behave unexpectedly. If integrations rely on assumptions, failures become silent, hard to diagnose, and costly to fix.
Boundary validation and consistent observability surface breaking changes early, reduce incident time, and protect the rest of the system from cascading failures.
Resilience patterns keep the product usable even when dependencies are degraded.
Practices that meet this principle
Validate downstream responses against schemas (for example: validate a response body matches an expected schema)
Validate external inputs at the boundary, and provide warnings for contract violations that matter
Log at integration boundaries (request, response, and errors) with sensible redaction and volume control
Use a standardised logging structure across all integrations to make searching and triage consistent
Extend type safety into query building and external data handling (for example: type-safe query builders such as Kysely or Drizzle)
Publish machine-readable interface documentation for async interactions (events, jobs, callbacks) where relevant (for example: AsyncAPI, OpenAPI callbacks, or an equivalent format)
Use kill switches for external integrations when appropriate (for example: outages, throttling, or degraded dependency performance). For example: wrap the integration call behind a runtime-configurable feature flag (LaunchDarkly, Unleash, or a database-backed config) so you can disable it without redeploying; or implement a circuit breaker that opens after a threshold of failures and routes to a safe fallback.
Apply resilience patterns: timeouts, retries with backoff, circuit breakers, and bulkheads
Validation
A project meets this principle when:
All integration boundaries validate the data they depend on, and detect breaking changes promptly
Boundary logs provide enough context to diagnose failures without requiring ad-hoc instrumentation
Logging is controllable (on and off, or sampled) and does not leak sensitive data
Integrations fail gracefully and can be disabled safely when dependencies are unhealthy
Resilience controls exist and are exercised (timeouts, retries, and circuit breakers)