How to choose between OpenAPI and AsyncAPI for microservices
Symptom & Diagnostic Output
When polyglot microservice architectures emit both synchronous HTTP responses and asynchronous Kafka/AMQP events, CI/CD pipelines frequently fail during contract validation. The absence of a unified API Contract Fundamentals & Tool Selection strategy causes duplicated JSON Schema definitions that diverge across independent deployments. The failure typically manifests with the following diagnostic output:
ERROR [contract-validator]: SchemaValidationError: Expected synchronous response schema (OpenAPI 3.1), received async message envelope (AsyncAPI 2.6). Contract drift detected in shared payload definitions. Field mismatch: 'user_id' (integer) vs 'userId' (string). Exit code 1.
This error indicates that frontend teams consuming REST endpoints and backend services publishing domain events are operating on desynchronized type definitions. The validator halts execution because structural parity between sync and async contracts cannot be guaranteed.
Root Cause Analysis
The architectural split stems from treating request-response and event-driven communication as isolated contract domains. Engineering teams default to an OpenAPI Specification Deep Dive for HTTP routing but fail to map identical domain objects to AsyncAPI message payloads. Without a centralized schema registry, identical types (e.g., UserCreated, OrderUpdated) are manually redefined in both specifications. This manual duplication introduces type coercion mismatches, missing required fields in async payloads, and version skew that breaks downstream consumer tests.
Resolution Workflow
To resolve contract drift and enforce parity across sync/async boundaries, implement the following diagnostic and remediation steps:
- Extract Shared Domain Models: Centralize language-agnostic JSON Schema definitions in a dedicated repository. Define base types using
draft-07ordraft-2020-12with strictadditionalProperties: falseto prevent silent field additions. - Configure OpenAPI References: Map
components/schemasto$refthe centralized base types. Ensuretype: objectandrequiredarrays match exactly across all HTTP response definitions. - Map AsyncAPI Payloads: Bind identical base types to AsyncAPI
components/messagesvia thepayloadfield. AppendcontentType: application/jsonand enforce identicalpropertiesdefinitions to guarantee structural parity. - Implement Cross-Spec Validation Hooks: Integrate
@stoplight/spectralorasyncapi-cli validateinto your CI pipeline. Patch the.spectral.yamlruleset to cross-validate OpenAPI and AsyncAPI schemas against the central registry. - Enforce Strict CI Parity Checks: Apply the following pipeline configuration to block deployments on schema divergence:
# ci/contract-validation.yml
validate_sync_async:
image: stoplight/spectral:latest
script: |
spectral lint openapi.yaml --ruleset .spectral.yaml
asyncapi validate asyncapi.yaml
spectral lint openapi.yaml asyncapi.yaml --ruleset .cross-spec-rules.yaml
Cross-Spec Validation Configuration
Deploy the following Spectral ruleset to operationalize automated parity enforcement. The ruleset validates reference integrity and payload mapping consistency across both specifications:
# spectral-ruleset.yaml
rules:
schema-parity-check:
description: Ensure OpenAPI and AsyncAPI schemas reference identical base types
severity: error
given: $.components.schemas.*
then:
field: $ref
function: pattern
functionOptions:
match: '^#/components/schemas/'
async-payload-mapping:
description: AsyncAPI message payloads must mirror OpenAPI response schemas
severity: error
given: $.components.messages.*.payload
then:
field: $ref
function: pattern
functionOptions:
match: '^#/components/schemas/'
Enable strictMode: true in your JSON Schema validators. Enforce unevaluatedProperties: false (draft-2019-09+) to block silent field additions. Configure OpenAPI x-asyncapi extensions to explicitly link synchronous endpoints to their corresponding async message topics, enabling automated cross-spec validation during CI.
Prevention & Governance
Establish a schema-first governance policy where all microservice contracts originate from a single source of truth. Enforce automated drift detection by integrating schema diffing into PR checks. Mandate uniform JSON Schema versions across sync and async boundaries. Deploy contract testing frameworks (e.g., Pact, Schemathesis) to validate both HTTP and message broker payloads against the unified registry prior to deployment. Regularly audit spec generation toolchains to ensure they inherit from centralized type definitions, eliminating ad-hoc schema declarations.