This repository implements a client-aware backward compatibility gateway for Node.js APIs. The gateway runs as a standalone service between API clients and the backend server and enforces backward compatibility at runtime. The backend only implements the latest API version; legacy clients are supported through deterministic, schema-driven request and response translation.
API evolution frequently introduces breaking changes such as:
- renamed fields
- modified request or response structures
- relocated endpoints
- changed value representations
Traditional approaches (multiple API versions, duplicated backend logic, client contract tests) increase maintenance cost or depend on client cooperation. This project provides:
- runtime compatibility enforcement
- no client-side tests
- no heuristic or AI-based inference
- deterministic and explainable behavior
Legacy Client (v1 / v2)
↓
Compatibility Gateway
↓
Latest Backend API
The gateway detects the client API version using URL prefixes (for example /v1/...) or version headers.
Compatibility decisions are made per client version, not globally.
Requests are resolved using:
(version, HTTP method, path) -> operationId
Each operation represents a semantic API action (for example user.create) and defines:
- schemas for each supported version
- deterministic translation rules (codecs)
- the corresponding latest backend endpoint
Each operation defines a canonical, version-independent representation that captures the meaning of the request or response.
legacy request -> canonical -> latest request
latest response -> canonical -> legacy response
This avoids N×N version-to-version mappings and keeps the system scalable.
The gateway uses JSON Schema (Ajv) to validate data at runtime. Validation is performed at multiple boundaries:
- legacy request validation
- translated latest request validation
- backend response validation
- translated legacy response validation Schemas are compiled into cached executable validators for performance.
All translations are explicit and rule-based:
- no inference
- no heuristics
- no AI-based decisions Behavior is predictable and reproducible.
1. Client sends legacy request
2. Gateway detects API version
3. Request resolved to operationId
4. Legacy request validated
5. Request decoded to canonical
6. Canonical encoded to latest format
7. Request forwarded to backend
8. Backend response validated
9. Response decoded to canonical
10. Canonical encoded to legacy format
11. Legacy response returned to client
Failures are classified precisely:
- legacy request validation failure -> client contract violation
- latest request validation failure -> translation logic error
- backend response validation failure -> backend contract violation
- legacy response validation failure -> reverse translation error
src/
server.js gateway entry point
versioning/ API version detection
registry/ operations, schemas, codecs
cache/ schema compilation and caching
proxy/ backend forwarding logic
tests/
*.test.mjs deterministic compatibility tests
Tests verify:
- correct request translation
- correct response translation
- rejection of invalid legacy requests No backend or client-side tests are required.
- research prototype
- runtime API compatibility reference
- compatibility metrics evaluation