API Versioning, Deprecation and Backward Compatibility Questions
Evolving an API without breaking existing consumers: versioning strategies (URI, header, media-type), distinguishing breaking from non-breaking changes, deprecation policies and sunset timelines, and coordinating migrations at scale. Covers communicating changes, supporting multiple versions concurrently, and compatibility guarantees across heterogeneous clients.
List the essential elements of a high-quality OpenAPI specification for a public REST endpoint. Explain why each element (paths, components/schemas, parameters, responses, securitySchemes, examples, operationId) matters for SDK generation, documentation, and tooling. Mention common pitfalls to avoid.
Sample Answer
Essential elements of a high-quality OpenAPI spec for a public REST endpoint and why they matter:
-
paths
- Why: define endpoints and HTTP methods; central for routing, client method names and autogenerated docs.
- Pitfall: ambiguous or duplicated paths, missing method-level details.
-
components/schemas
- Why: canonical models for requests/responses used by SDK generators to create typed classes and by docs to show shapes.
- Pitfall: overly generic object/any, circular references, missing required properties.
-
parameters (path, query, header)
- Why: drives SDK function signatures, validation rules, and example curl commands in docs.
- Pitfall: undocumented defaults, inconsistent naming or types, using query for large payloads.
-
responses (status codes + content)
- Why: maps to SDK exceptions/return types and clear user-facing docs; enables tooling to generate tests and mock servers.
- Pitfall: returning vague 200 with mixed payloads, missing error schemas, no examples per status.
-
securitySchemes
- Why: describes auth flows (OAuth2, API key, bearer) so SDKs wire auth helpers and docs show how to authenticate.
- Pitfall: undocumented token scopes, or mixing schemes without clear usage per operation.
-
examples
- Why: concrete request/response payloads improve docs readability, speed onboarding, and enable realistic mock servers and tests.
- Pitfall: stale examples that don’t match schemas.
-
operationId
- Why: stable, unique identifier used by code generators to name functions/methods—critical for stable SDKs and changelog-friendly evolution.
- Pitfall: auto-generated or changing IDs across versions causing breaking SDK changes.
Additional best practices:
- Use clear descriptions and tags for organization and discoverability.
- Version the API spec and use semantic versioning.
- Validate spec with linters and CI to catch schema mismatches.
- Include pagination, rate-limit headers, and idempotency guidance.
Avoid: inconsistent types, missing content-type declarations, and coupling implementation details into the contract. A precise, versioned, and example-rich spec enables reliable SDK generation, trustworthy docs, and robust tooling integration.
Design a reliable webhook delivery system for third-party clients. Requirements: at-least-once delivery, exponential backoff retries with jitter, payload signing for verification, dead-letter queue for permanent failures, replay capability, and limited ordering guarantees. Describe event storage, retry scheduler, acknowledgement semantics, and client expectations for idempotency.
Sample Answer
Clarify requirements
- Deliver events to third-party HTTP endpoints at-least-once.
- Retry with exponential backoff + jitter, move permanent failures to DLQ.
- Sign payloads for verification, support replay, provide limited ordering guarantees.
- Clients must handle idempotency.
High-level architecture
- Event API → Event Store (append-only) → Retry Scheduler → Delivery Workers → Client endpoints
- DLQ storage for permanently failed deliveries
- Replay API to re-queue events
Event storage
- Append-only store (e.g., PostgreSQL partitioned table, DynamoDB, or Kafka topic) holding: event_id (UUID), client_id, payload, created_at, seq_id (per-client monotonic), status (pending/in-flight/succeeded/failed/dlq), attempt_count, next_retry_at, last_error, signed_headers.
- Keep immutable payloads; mutable metadata in separate table for efficient updates.
Payload signing
- Sign each event body with HMAC-SHA256 using client-specific secret; include headers: X-Event-Id, X-Signature, X-Timestamp, X-Seq-Id.
- Server also stores secret fingerprint for rotation; support ephemeral keys.
Retry scheduler
- Use a distributed priority queue keyed by next_retry_at (Redis sorted set or scheduler DB query + worker pool).
- Backoff: next_delay = base * 2^(attempt_count-1) with full jitter: sleep = random(0, next_delay). Cap max_delay (e.g., 24h) and max_attempts (e.g., 10).
- Scheduler enqueues due events to delivery worker queue; workers mark as in-flight with lease TTL to avoid duplicates.
Delivery & acknowledgement semantics
- Consider 2xx responses as ACK -> mark succeeded.
- 3xx/4xx/5xx:
- 5xx and network errors: retry (increment attempt_count, set next_retry_at using backoff+jitter).
- 4xx: treat as permanent for certain codes (e.g., 400 invalid payload -> DLQ); 429 (rate limit) -> retry with Retry-After override.
- 410 (Gone) -> stop and mark client unsubscribed; optionally DLQ.
- If worker crashes while in-flight, lease TTL expiry returns event to pending for retry.
- Delivery is at-least-once; duplicate deliveries possible.
Dead-letter queue (DLQ)
- After max_attempts or certain permanent errors, move event metadata to DLQ storage with failure reason and timestamps.
- Expose DLQ UI/API for inspection, manual retry, or deletion.
Replay capability
- Replay API: client or operator can request re-delivery by event_id, time range, or seq range. Replay creates new pending deliveries (preserve original event_id and seq_id) to maintain idempotency keys.
Ordering guarantees
- Provide limited ordering per client by partitioning workers per client or per client shard and delivering events with increasing seq_id when possible.
- Guarantee: best-effort in-order delivery per partition; if a later event retries more than an earlier one, ordering can be violated. Recommend clients design for idempotency and partial-order tolerance.
Client expectations (idempotency & best practices)
- Use event_id and seq_id headers to dedupe/process idempotently.
- Validate HMAC signature and timestamp window (reject old/future timestamps).
- Return 2xx only after durable processing; for async processing, return 202 and provide a separate callback if needed.
- Honor Retry-After and use idempotent handling for repeated deliveries.
Observability & operational controls
- Metrics: attempt_count distribution, delivery latency, DLQ rate, success rate per client.
- Alerting on DLQ spikes, high error rates.
- Client-configurable settings: max_attempts, backoff base/cap, concurrency, ordering strictness.
Trade-offs & rationale
- Append-only store + metadata separation simplifies replay and audit.
- Full jitter avoids thundering herd.
- Per-client partitioning gives reasonable ordering without sacrificing scale.
- At-least-once + idempotent client design keeps the system simple and reliable; exactly-once would require two-phase commit or per-client transactional endpoints which is impractical for third parties.
This design balances reliability, scalability, security, and operational control while clearly setting client responsibilities for idempotency and verification.
Design an API gateway layer for a multi-tenant SaaS application that centralizes authentication, rate limiting, routing, and observability. Requirements: tenant isolation for quotas, per-tenant whitelisting/blacklisting of endpoints, minimal per-tenant overhead, and ability to change policies without redeploying gateway code. Outline components and configuration flows.
Sample Answer
Requirements (clarified)
- Functional: central auth, routing, per-tenant quotas, per-tenant allow/deny of endpoints, dynamic policy changes without redeploy.
- Non-functional: minimal per-tenant runtime overhead, strong isolation for quotas, observability, scalable.
High-level architecture
Client -> Edge LB -> API Gateway Cluster (stateless proxies) -> Auth & Policy Service(s) -> Backend Services
Supporting services: Tenant Config Store, Rate-Limit Store, Policy Engine, Metrics/Logging, Admin UI & CI pipeline.
Core components
- Stateless Gateway Proxy (Envoy/NGINX+Lua/Kong): performs TLS, extracts tenant id (JWT/client cert/header), enforces fast-path checks via local cache, routes to backend.
- Policy & Auth Service: central authn/authz, issues/verifies JWTs, exposes dynamic policy API. Integrates with identity provider (OIDC).
- Policy Engine (Rego/Open Policy Agent): evaluates fine-grained allow/deny rules (per-tenant) and outputs decision; versioned policies stored in config store.
- Tenant Config Store (etcd/Consul/DB): stores tenant metadata, quota plans, whitelists/blacklists, policy pointers.
- Rate-Limit Store (Redis/Clustered): token-bucket or leaky-bucket per-tenant counters; supports local caching + periodic sync to minimize RTT.
- Config Distribution: push-based (watch/stream) from Tenant Config Store to gateway proxies for immediate changes, fallback poll.
- Observability: distributed tracing (Jaeger), structured logs, metrics (Prometheus) with tenant and endpoint labels; dashboards and alerting.
- Admin UI / APIs: operators and tenant admins can change quotas, rules, and whitelists; changes update store and push to gateways.
Configuration & control flow
- Provision: Tenant entry created in Config Store with quotas, policy IDs, whitelist/blacklist entries.
- Runtime request:
- Gateway extracts tenant id from JWT or header.
- Local cache of tenant config used for fast checks (whitelist/blacklist). If cache miss, gateway queries Policy Service.
- Gateway queries Rate-Limit Store (local token-bucket refills + Redis fallback) to enforce quota. Keys are tenant:quota_plan:endpoint.
- For complex rules, gateway calls Policy Engine (local sidecar or remote) with context (tenant, endpoint, claims) and enforces decision.
- Audit & metrics emitted with tenant-id, outcome, latency.
Tenant isolation & minimal overhead
- Use hierarchical quotas: global per-tenant bucket plus per-endpoint sub-buckets to avoid many small counters.
- Local in-memory caches + stamped token-buckets reduce remote calls; only miss/overflow hits Redis/Policy Service.
- Shard rate-limit keys and use Redis Cluster with TTLs to scale counters.
Dynamic policies without redeploy
- All rules and whitelists live in Config Store and Policy Engine (Rego). Gateways subscribe to changes via watch/stream or xDS; Policy Engine bundles and validates policies before push. No code changes required.
Scalability & resilience
- Autoscale gateway fleet behind LB.
- Use Redis Cluster with client-side sharding for rate limits.
- Policy Engine can be run as local sidecar (low latency) with periodic sync from central manager.
- Graceful degradation: if policy store unavailable, fallback to safe default (deny or permissive depending on SLA) and emit alerts.
Trade-offs
- Strong consistency for quotas requires sync and increases latency; mitigated via local approximation + eventual consistency.
- Sidecar Policy Engine increases memory but reduces latency vs remote calls.
- Complexity added by push-based config distribution pays off for low-latency policy changes.
Monitoring & SLOs
- Track per-tenant error rate, throttle rate, auth failures, policy evaluation latency.
- Alerts on unusual quota bursts, policy push failures, or high miss rates on caches.
This design centralizes auth, routing, quotas, and observability, enforces per-tenant isolation, supports dynamic policy updates, and minimizes per-tenant runtime overhead through caching and hierarchical quotas.
How would you manage API evolution for a platform with thousands of third-party clients so you can innovate while minimizing breakage? Propose governance, tooling, deprecation policy, automated compatibility checks, SDK management, migration telemetry, and incentives to encourage clients to upgrade.
Sample Answer
Situation: We support a platform used by thousands of third‑party clients that must keep evolving without causing widespread breakage.
Approach (high level): Treat API evolution as a product with clear governance, automated safety nets, observability, and developer experience incentives so we can iterate fast while keeping clients safe.
Governance:
- API Council (engineering + product + solutions architects + PMs + major client reps) meets biweekly to approve changes.
- Change categories: non‑breaking additive, opt‑in features, versioned breaking changes. Each change must include customer impact, migration plan, and rollout window.
- Change approval gates: design doc, test plan, deprecation schedule, SDK updates.
Tooling & automated checks:
- Contract testing pipeline using OpenAPI/JSON Schema: every PR runs strict backwards‑compatibility checks (e.g., Spectral, openapi-diff, or custom checker) to detect removals/type changes.
- Integration sandbox with traffic replay to run changes against recorded client requests; flag failures.
- CI enforces semantic version bump rules and prevents accidental breaking changes.
Deprecation policy:
- Minimum 12 months for public breaking changes; staged: announcement → opt‑in feature flag → official deprecation start → removal after window.
- Public changelog, calendar with cutover dates, automated email and dashboard notices to registered clients.
- Provide compatibility mode (server-side feature flags) to allow gradual cutover.
SDK management:
- Maintain first‑class SDKs with version parity and automatic generation from API spec (OpenAPI) to reduce drift.
- Release SDKs concurrently with API changes; each SDK release includes migration guides and codemods for common languages.
- Publish migration samples and quickstart notebooks.
Migration telemetry & support:
- Instrument endpoints to record client usage by API key, version, and feature flag. Track upgrade rate, error spikes, and which clients still call deprecated endpoints.
- Dashboard for customer success/solutions architects to proactively contact high‑value clients still on old versions.
- Offer migration sandboxes, migration sprints, and paid engineering days for enterprise customers.
Incentives to upgrade:
- Default new features only available to latest API versions; backport only critical fixes.
- Performance/security improvements gated to newer versions; announce performance benchmarks.
- Offer migration incentives: extended support SLA, discounted professional services, or early access to beta features for clients who upgrade within window.
Tradeoffs:
- Longer deprecation windows slow full cleanup but reduce business risk.
- Automation upfront costs pay off by reducing manual client churn and emergency fixes.
Result: This combines policy, automation, SDK hygiene, observability, and commercial incentives so the platform can innovate while minimizing client breakage and giving Solutions Architects the tools to help customers migrate successfully.
Design an audit logging and access-trail architecture for APIs in regulated industries. Requirements: record who accessed which resources, when, and what was returned (or a masked summary); logs must be tamper-evident, encrypted at rest, searchable for investigations, and comply with retention policies. Describe log schema, storage choices, indexing strategy, and integration with SIEM tools.
Sample Answer
Requirements (clarify): immutable, tamper-evident, encrypted-at-rest, searchable, masked or full response capture, retention & deletion policies, SIEM integration, low-latency for investigations.
High-level architecture:
- API Gateway / Ingress captures request/response metadata and optionally body (full or masked) and forwards to an Audit Service.
- Audit Service enriches events (user ID, client app, auth token, request-id, geo, service, resource path, HTTP verb, response status, latency), applies masking/redaction rules, signs each record, and writes to an append-only store.
- Append-only store choices: AWS QLDB / DynamoDB with ledger-mode / GCP Cloud Audit Logs + CMEK & WORM buckets / Azure ADLS with Immutable storage. For multi-cloud/on-prem, use an append-only object store (S3 with Object Lock + Glacier Vault Lock) + periodic Merkle-root publishing to a transparency log.
- Search/index: stream events to an indexing cluster (OpenSearch/Elasticsearch or ClickHouse) via Kafka/EventBridge for fast querying; raw signed records retained in cold immutable storage.
- Tamper-evidence: each record includes a hash and previous-record-hash (hashchain) and periodic root signed by a KMS-protected key; optionally anchor roots to external blockchain or public transparency log.
- Encryption: envelope encryption with KMS (customer-managed keys), all transports via TLS; separate keys per environment/tenant.
- Retention & lifecycle: S3 lifecycle rules or DB TTL that move indexed copies to cold archive; deletion only by retention-control service which records deletions as signed events (immutable audit).
- Access controls & monitoring: RBAC, MFA, just-in-time access for investigators; access to logs is itself logged and auditable.
- SIEM integration: provide normalized CEF/LEEF and JSON output via connectors (Filebeat/Fluentd, Kafka Connect, or Splunk HEC). Support syslog and REST ingest with guaranteed delivery and backpressure.
- Schema (JSON example):
{
"event_id":"uuid",
"ts":"ISO8601",
"actor":{"id":"user@corp","type":"user","roles":["admin"]},
"client":{"id":"app-id","ip":"1.2.3.4","user_agent":"..."},
"request":{"method":"GET","path":"/accounts/123","query":"..."},
"resource":{"type":"account","id":"123"},
"response":{"status":200,"masked_summary":"balance:MASKED","sha256_of_full":"..."},
"auth":{"token_id":"...","mfa":true},
"trace":{"trace_id":"..."},
"hash":"sha256(...)", "prev_hash":"...",
"signature":"kms-sig"
}
Indexing strategy:
- Index key fields: event_id, ts, actor.id, resource.type/id, request.path, response.status, trace_id.
- Time-partitioned indices (daily/hourly); roll-over and shrink for retention.
- Store enriched, stripped-down index for fast searches; link to raw signed object via event_id URI.
- Support secondary indexes for compliance filters (PII flags, masked vs full).
Operational considerations & trade-offs:
- Full response capture increases risk — prefer storing full responses in secure cold store with stricter access controls and only store masked summaries in hot index.
- Trade-off between searchability and cost: keep hot indexed minimal fields; use asynchronous enrichment to avoid API latency.
- Ensure key management and log signing keys rotate per policy; provide key escrow for legal holds.
- Testability: tamper-detection drills, retention/deletion audits, SIEM correlation tests.
This design provides immutable, encrypted, searchable audit trails that integrate with enterprise SIEMs and meet regulated-industry controls while balancing performance, cost, and privacy.
Unlock Full Question Bank
Get access to all API Versioning, Deprecation and Backward Compatibility interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.