Reliability and Performance EngineeringIntroductionA RESTful API is not successful merely because it returns the correct representation. It must continue to behave predictably when clients retry requests, networks become slow, traffic increases, dependencies fail, and resources are contested. Reliability and performance engineering therefore treat an API as a socio-technical system: software, infrastructure, clients, operators, and business expectations interact to determine user experience. Reliability concerns the probability that a service performs its intended function under stated conditions for a stated period. Performance concerns how efficiently it responds to demand. These properties are related but not identical. A service may be fast under light load yet unreliable during a traffic spike; it may also be highly available but consistently slow. This chapter develops a practical framework for designing standardized errors, retries, timeouts, rate limits, idempotency, caching, and resilience patterns, then measuring latency, throughput, availability, and scalability against service objectives. Learning ObjectivesBy the end of this chapter, you should be able to: - Design consistent, machine-readable REST API errors.
- Choose timeout, retry, backoff, and jitter policies safely.
- Apply rate limiting, quotas, idempotency keys, and concurrency controls.
- Select and invalidate caches while reasoning about freshness and consistency.
- Explain circuit breakers, bulkheads, load shedding, and graceful degradation.
- Calculate and interpret latency, throughput, availability, error budgets, and capacity measures.
- Translate user and business requirements into service-level objectives (SLOs).
- Evaluate reliability designs through testing, observability, governance, and ethical practice.
1. Reliability as a Design PropertyReliability is designed into an API contract rather than added after deployment. The contract should specify valid inputs, output representations, status codes, error semantics, authentication behavior, rate limits, consistency expectations, and timing expectations. A client can recover from a failure only when the failure is represented clearly enough to guide action. A useful distinction is: - Availability: whether the service is usable when requested.
- Durability: whether accepted data remains intact.
- Correctness: whether the response or state transition is semantically right.
- Resilience: whether the system withstands and recovers from disruption.
- Performance: the observable response and resource behavior under demand.
Reliability is often described probabilistically. If a component has a constant failure rate λ per hour and failures follow an exponential model, its reliability over time t is: R(t) = e^(−λt) Here, R(t) is the probability of surviving without failure for time t, and λ is the constant failure rate in failures per unit time. This model assumes independent failures and a constant hazard rate; it is useful for simple availability reasoning but does not describe every software failure, especially correlated overload or configuration errors. 2. Standardized Error Design2.1 HTTP semantics and application errorsHTTP status codes communicate broad classes of outcomes. A well-designed API uses them consistently: | Situation | Typical status | Meaning for the client |
|---|
| Successful retrieval | 200 OK | Representation returned | | Successful creation | 201 Created | Resource created; location may be supplied | | Accepted asynchronous work | 202 Accepted | Processing has begun but is incomplete | | Successful deletion with no body | 204 No Content | Operation completed | | Invalid syntax or shape | 400 Bad Request | Request cannot be processed as sent | | Missing or invalid authentication | 401 Unauthorized | Credentials are absent or unacceptable | | Authenticated but disallowed | 403 Forbidden | Identity lacks permission | | Resource absent or intentionally undisclosed | 404 Not Found | Target is unavailable to the client | | State conflict | 409 Conflict | Request conflicts with current resource state | | Validation failure | 422 Unprocessable Content | Syntax is valid but semantic rules fail | | Too many requests | 429 Too Many Requests | Client must reduce demand | | Unexpected server failure | 500 Internal Server Error | Server could not fulfill request | | Dependency or gateway failure | 502/503/504 | Upstream failure, temporary unavailability, or timeout |
Status codes should not expose internal stack traces, database details, tokens, or personal information. Logs may contain diagnostic context, but responses should contain safe, actionable information. 2.2 Problem detailsA standardized error body can use the problem-details style: {
"type": "https://api.example.edu/problems/invalid-parameter",
"title": "Invalid parameter",
"status": 422,
"detail": "The page size must be between 1 and 100.",
"instance": "/requests/7f3a",
"code": "PAGE_SIZE_OUT_OF_RANGE",
"requestId": "req-91c2"
}The type identifies the problem class, title provides a stable short label, status repeats the HTTP status, detail explains the particular occurrence, and instance identifies the occurrence without exposing secrets. An application-specific code enables localization and reliable client branching. Clients should generally branch on status and documented codes, not on free-form detail text. Errors should be observable as well as understandable. A correlation or request identifier should connect the client response with server-side traces. Validation errors should identify fields and constraints in a structured manner. Security-sensitive systems must avoid revealing whether a protected resource exists when such disclosure would enable account or data enumeration. 3. Timeouts, Retries, and Backoff3.1 Timeouts are resource controlsA timeout bounds how long a caller waits for an operation. Without a deadline, a stalled dependency can consume threads, sockets, memory, and connection-pool capacity until the whole service fails. Timeouts should be set at several layers: connection establishment, TLS negotiation, reading response data, and the overall request deadline. The end-to-end deadline must be propagated to downstream services so that work is not continued after the caller has abandoned it. Timeout selection should be evidence-based. Measure normal and tail latency, then leave a margin for expected variation. A timeout is not a promise that the server will finish by that time; it is a caller-side decision to stop waiting. The server may still complete the work, which is particularly dangerous for non-idempotent operations. 3.2 When retries are safeRetries can recover from transient failures such as connection resets, temporary overload, or unavailable dependencies. They can also amplify an outage. A retry is usually appropriate only when: - The failure is plausibly transient.
- The operation is safe to repeat, or is protected by idempotency.
- The retry budget and deadline allow another attempt.
- The request is not likely to worsen overload.
GET, HEAD, PUT, and DELETE are defined as idempotent in HTTP semantics, meaning repeating the same intended request has the same intended effect, although side effects such as logging may occur. POST is not inherently idempotent. A service may make a POST operation safely repeatable by requiring an idempotency key. 3.3 Exponential backoff and jitterA common capped exponential-backoff schedule is: dn = min(dmax, d0 × 2n) where dn is the delay before attempt n, d0 is the initial delay, dmax is the maximum delay, and n begins at 0 for the first retry. This formula assumes a retry policy with a finite cap. Random jitter prevents many clients that failed simultaneously from retrying simultaneously. With full jitter, the actual delay is selected uniformly from 0 through dn. A retry policy should specify maximum attempts, total deadline, retryable status codes, and whether request bodies can be replayed. For example, 429 and 503 may be retriable when a Retry-After value is honored; a 400 validation error normally is not. Retrying a 401 error without correcting credentials is ineffective. The expected request pressure can be increased by retries. If each original request generates, on average, r additional attempts, total attempt rate is approximately: λtotal = λoriginal × (1 + r) This approximation assumes a stable average and ignores feedback effects. During an outage, r can rise sharply, producing a retry storm. Therefore retry budgets should be enforced at clients, gateways, and services. 4. Idempotency Keys and Exactly-Once IllusionsA client may lose a response after the server has committed an operation. It cannot know whether the operation failed or merely whether the response was lost. An idempotency key lets the server associate repeated attempts with one logical operation. A robust design stores, for each authenticated client and key: - the operation scope and request fingerprint;
- the first accepted result, including status and response body;
- a retention expiration time;
- a state such as processing, succeeded, or failed.
A repeated request with the same key and the same payload should return the stored result. The same key with a different payload should produce a conflict, commonly 409. Concurrent requests using the same key require atomic creation or locking so that two workers do not perform the operation twice. Idempotency is not the same as exactly-once execution. A process can crash after an external side effect but before recording completion. Reliable workflows use transactional outbox patterns, deduplication at consumers, reconciliation jobs, or provider-supported idempotency. Keys must be scoped to the principal and operation, generated with sufficient unpredictability, and protected from leaking sensitive data. 5. Rate Limits, Quotas, and Load ProtectionRate limiting controls demand over time; quotas control aggregate consumption over a longer period. A rate limit may protect a service from bursts, while a quota may represent a daily or monthly entitlement. Limits should be documented, observable, and applied fairly. Two common algorithms are: - Token bucket: tokens accumulate at rate r up to capacity B. Each request consumes tokens. Bursts up to B are permitted if tokens have accumulated.
- Leaky bucket: requests enter a queue and leave at a controlled rate, smoothing output but potentially increasing waiting time.
A token-bucket implementation can be expressed conceptually as: Tnew = min(B, Told + r × Δt) − c where Told and Tnew are token counts, r is tokens per second, Δt is elapsed time in seconds, B is bucket capacity, and c is request cost. The request is admitted only if the resulting token count is non-negative. The equation assumes a continuously replenished conceptual model; production implementations use timestamps and integer or fixed-point arithmetic. A rejected request should normally return 429 and may include Retry-After and limit metadata. Limits should be keyed appropriately: by authenticated principal, tenant, API key, IP address, route, or a combination. IP-only controls can unfairly penalize users behind a shared network, while identity-only controls can fail to protect unauthenticated endpoints. Rate limiting is one layer of defense, not a substitute for authorization, input validation, capacity planning, or abuse monitoring. Emergency load shedding may reject low-priority work to preserve critical functions. 6. Caching and ConsistencyCaching reduces latency, bandwidth, and backend load by reusing a representation. It can exist in browsers, reverse proxies, CDNs, API gateways, or application memory. Cache policy must answer four questions: what is cacheable, who may reuse it, how long it is fresh, and how it is invalidated. HTTP caching commonly uses validators. A server may return an ETag; a client later sends If-None-Match. If the representation is unchanged, the server returns 304 Not Modified without retransmitting the body. Cache-Control controls freshness and sharing. Private, user-specific data must not be placed in a shared cache unless the policy safely separates it. A simple expected latency model for a cache is: Lexpected = h × Lhit + (1 − h) × Lmiss where h is the cache-hit ratio between 0 and 1, and Lhit and Lmiss are hit and miss latencies in the same unit. This assumes two representative classes and does not include refresh, eviction, or queueing costs. For example, if the hit ratio is 0.80, hit latency is 10 ms, and miss latency is 110 ms, then expected latency is 0.80×10 + 0.20×110 = 30 ms. Caching introduces staleness and invalidation complexity. Time-to-live is easy to operate but may serve old data. Explicit invalidation improves freshness but can fail when events are lost. Versioned resources, conditional requests, stale-while-revalidate, and write-through or write-behind strategies each make different consistency trade-offs. A cache should never be used to conceal an authorization decision that has not been correctly evaluated. 7. Resilience PatternsCircuit breakersA circuit breaker monitors failures or slow calls. In the closed state, calls flow normally. When a threshold is reached, it opens and rejects calls quickly. After a cool-down period, it enters a half-open state and permits limited probes. Success closes the circuit; further failure opens it again. The breaker prevents a failing dependency from consuming all local resources, but thresholds must account for sample size and traffic volume. BulkheadsBulkheads isolate resources so that one workload cannot exhaust everything. Separate connection pools, thread pools, queues, or concurrency limits can isolate tenants or dependency classes. Isolation improves fault containment but may leave capacity unused; allocation should reflect business criticality. Graceful degradationA service may return a cached profile instead of live recommendations, disable an optional enrichment, or accept an order while deferring noncritical notifications. Degradation must be explicit and safe. It must not silently weaken authorization, data integrity, or financial controls. Health checks and load sheddingLiveness checks answer whether a process should be restarted; readiness checks answer whether it should receive traffic. A dependency failure should not necessarily make every instance fail liveness. Load shedding rejects work early when queues or resource utilization exceed safe limits. Queue lengths, concurrency, and deadlines are often more useful triggers than CPU alone. 8. Measuring Performance and Service Objectives8.1 Core metrics- Latency: elapsed time from a defined start event to a defined completion event. Report distributions, especially p50, p95, p99, and maximum observed values; averages can hide tail behavior.
- Throughput: completed successful operations per unit time, such as requests per second or orders per minute.
- Error rate: failed or otherwise unacceptable operations divided by total relevant operations, with a clearly documented denominator.
- Availability: proportion of time or valid requests during which the service meets its availability criterion.
- Saturation: degree to which a constrained resource—connections, CPU, memory, queue, or database capacity—is being consumed.
For request-based availability: Availability = (successful eligible requests ÷ total eligible requests) × 100% The definition of “successful” must be agreed in advance. A 200 response containing incorrect data should not automatically count as success. If a service is available 99.9% of a 30-day month, the permitted unavailability is: 30 × 24 × 60 × (1 − 0.999) = 43.2 minutes This calculation assumes a 30-day month and treats all minutes equally. A 99.99% target would permit 4.32 minutes under the same assumption. 8.2 SLIs, SLOs, and SLAsA service-level indicator (SLI) is a measured quantity, such as the fraction of valid requests completed under 300 ms. A service-level objective (SLO) is a target for that indicator, such as 99.9% availability or 95% of reads under 300 ms. A service-level agreement (SLA) is a contractual commitment, often including remedies. An SLO should be stricter than an SLA only when the organization can operate to that internal standard; otherwise it creates false confidence. The error budget is the permitted unreliability: Error budget = 1 − SLO For an availability SLO of 99.9%, the error budget is 0.1% of eligible requests or time. Error budgets support engineering decisions: if a service has exhausted its budget, risky releases may be paused in favor of reliability work. 8.3 Capacity and scalabilityThroughput under load is not automatically scalable. Vertical scaling increases resources on one instance; horizontal scaling adds instances. Scaling can be limited by a database, lock, external API, network, or coordination protocol. A useful utilization relationship is Little’s Law: N = λ × W N is the average number of items in a stable system, λ is average arrival or throughput rate, and W is average time in the system. Units must be compatible: requests/second multiplied by seconds/request yields requests. The law assumes a stable long-run system and averages over the same population; it does not by itself determine capacity or tail latency. For example, at 50 requests per second and an average end-to-end time of 0.20 seconds, the average in-flight population is 10 requests. If latency rises to 1 second at the same throughput, approximately 50 requests are in flight, increasing pressure on pools and memory. Performance tests should include load tests at expected demand, stress tests beyond capacity, spike tests, soak tests over time, and resilience tests involving dependency failures. Results must record workload mix, data size, warm-up, cache state, client concurrency, infrastructure, and resource saturation; otherwise comparisons are misleading. 9. Observability and DiagnosisMetrics show aggregate behavior, logs provide event detail, and traces show request paths across services. A request identifier should be propagated across these signals. High-cardinality labels require care: unbounded user IDs or URLs can make monitoring itself expensive. Useful dashboards correlate latency percentiles, throughput, errors, saturation, cache-hit ratio, retry counts, timeout counts, queue depth, and dependency health. Alerting should be based on user impact and sustained conditions rather than every transient fluctuation. Burn-rate alerts compare current error-budget consumption with the time remaining in the SLO window. Observability data is sensitive. Logs should be minimized, access-controlled, retained only as necessary, and scrubbed of credentials, payment data, health information, and unnecessary personal identifiers. 10. Illustrative Case: University Enrollment APIBackgroundA university exposes a REST API for course enrollment. Students search courses, view seat availability, and submit enrollment requests. During registration, demand rises from 20 to 300 requests per second. The enrollment database is authoritative, while a recommendation service is optional. ProblemThe initial service has three failures. First, clients retry timed-out POST requests, occasionally creating duplicate enrollment attempts. Second, a slow recommendation dependency consumes connection-pool capacity and causes enrollment requests to fail. Third, course searches repeatedly query the database, producing high latency during peak demand. AnalysisMeasurements show a 95th-percentile search latency of 1.2 seconds during registration, a recommendation timeout rate of 8%, and database saturation above 85%. The team defines these initial SLOs: 99.9% of valid enrollment requests should receive a definitive accepted or rejected result within 2 seconds, and 99% of course searches should complete within 500 ms. Availability and correctness are measured separately because a fast but incorrect seat count is unacceptable. Approach and solutionThe team introduces a standardized problem-details response with a request ID and stable error codes. Enrollment POST requests require an idempotency key. The service atomically records the key and enrollment result, preventing duplicate processing. A two-second end-to-end deadline is propagated to dependencies; retries are limited to one attempt for transient dependency failures and use jittered backoff. A circuit breaker and bulkhead isolate recommendations. If recommendations fail, search results remain available without them. Course metadata is cached with a short TTL and ETags, while seat availability is fetched from the authoritative enrollment store or represented with an explicitly documented freshness policy. A token bucket limits each student account and protects the database from abusive bursts. Load tests use realistic search-to-enrollment ratios and concurrent users. Tracing identifies database queries that lack suitable indexes. Dashboards track p95 and p99 latency, enrollment correctness, duplicate suppression, retry volume, cache hits, and database saturation. OutcomeIn the test environment, cached searches reduce database read traffic, and the recommendation bulkhead prevents its failures from consuming enrollment capacity. Idempotency eliminates duplicate enrollment records in fault-injection tests. The team does not claim success from latency alone: it verifies seat-allocation correctness and tests simultaneous requests for the final available seat. Learning pointsThe case demonstrates that reliability is cross-layer. Idempotency addresses uncertain client outcomes; deadlines and breakers control dependency failure; caching reduces predictable load; rate limits protect scarce resources; and SLOs make trade-offs measurable. It also shows why a cache must not replace an authoritative transaction when correctness is critical. 11. Governance, Ethics, and Contemporary PracticeReliability controls can affect people unevenly. Rate limits based solely on IP address may disadvantage users on shared networks. Automated fraud controls may block legitimate users without an appeal path. Aggressive caching can expose private information if cache keys omit tenant or authorization context. Error messages can leak sensitive existence or identity information. Design reviews should therefore include threat modeling, privacy impact analysis, accessibility considerations, tenant isolation, and clear operational ownership. Compliance obligations may require audit trails, retention controls, data residency, incident reporting, or deletion support. Reliability does not justify indefinite logging or indiscriminate collection. Contemporary platforms increasingly use service meshes, adaptive concurrency limits, distributed tracing, OpenTelemetry-compatible telemetry, and automated canary analysis. AI-assisted operations can summarize incidents or detect anomalies, but automated remediation requires guardrails, human oversight, explainable thresholds, and rollback mechanisms. A model should not be allowed to change production rate limits or delete data without authorization and auditable controls. 12. Implementation Best Practices- Define success, failure, latency, and eligibility precisely before measuring.
- Set deadlines at the caller and propagate them downstream.
- Retry only transient failures, with bounded attempts, jitter, and a total budget.
- Make non-idempotent operations safely repeatable through idempotency keys and atomic storage.
- Use 429 responses and documented limits rather than silently dropping requests.
- Cache only data whose freshness and privacy requirements are understood.
- Isolate optional or unreliable dependencies with bulkheads and circuit breakers.
- Prefer tail-latency percentiles and workload-specific tests to averages alone.
- Monitor errors, latency, traffic, and saturation together.
- Connect SLOs to error budgets, release decisions, and incident learning.
- Test failure modes deliberately, including lost responses, duplicate requests, stale caches, dependency timeouts, and traffic spikes.
- Treat security, privacy, correctness, and fairness as reliability requirements.
Challenges and LimitationsNo single pattern guarantees reliability. Retries can cause overload; caching can return stale data; breakers can reject useful work; rate limits can harm legitimate clients; and high availability can conflict with strong consistency. Metrics can be gamed by changing denominators or excluding difficult requests. Distributed systems also suffer from partial failure and imperfect clocks, making global coordination expensive. Capacity models are approximations. Averages hide tail behavior, Little’s Law does not predict queue disciplines, and an availability percentage can conceal a severe localized outage. Consequently, quantitative analysis must be combined with controlled experiments, code review, incident evidence, and domain knowledge. Chapter SummaryReliable REST APIs use explicit contracts, safe error representations, deadlines, bounded retries, backoff with jitter, rate limits, idempotency, and carefully governed caching. Resilience patterns such as circuit breakers, bulkheads, graceful degradation, health checks, and load shedding prevent local failures from becoming systemic outages. Performance engineering measures latency distributions, throughput, error rates, availability, and saturation under realistic workloads. SLIs and SLOs convert expectations into measurable targets, while error budgets connect reliability to release management. Little’s Law and cache-latency models provide useful quantitative reasoning when their assumptions are respected. Finally, observability, privacy, security, fairness, and correctness are integral to professional reliability engineering rather than optional additions. Key TermsReliability: Probability that a system performs its intended function under stated conditions. Availability: Proportion of eligible time or requests in which a service meets its availability criterion. Latency: Elapsed time between defined request and completion events. Throughput: Completed work per unit of time. Saturation: Degree to which a constrained resource is being consumed. SLO: Target value for a measured service-level indicator. SLI: Quantitative measurement of service behavior. SLA: Contractual service commitment, often with remedies. Error budget: Permitted unreliability implied by an SLO. Idempotency: Property that repeating an intended operation produces the same intended effect. Idempotency key: Client-supplied identifier used to deduplicate logical operations. Timeout: Limit on how long a caller waits for an operation. Exponential backoff: Retry delay that increases geometrically between attempts. Jitter: Random variation added to retry timing to avoid synchronized retries. Rate limit: Restriction on request frequency or concurrency. Token bucket: Rate-limiting algorithm permitting controlled replenishment and bursts. Cache validator: Metadata, such as an ETag, used to determine whether a representation changed. Circuit breaker: Failure-control mechanism that temporarily stops calls to an unhealthy dependency. Bulkhead: Isolation of resources so one workload cannot exhaust all capacity. Load shedding: Deliberate rejection of work to protect essential service functions. Review QuestionsShort Answer Questions- Why should an API avoid returning stack traces in client-facing errors?
- What problem does an idempotency key solve after a response is lost?
- Distinguish an SLI from an SLO.
- Why is jitter added to exponential backoff?
- What is the purpose of a circuit breaker?
Long Answer Questions- Explain how timeout, retry, backoff, and idempotency policies should work together for a payment-like REST operation.
- Compare token-bucket and leaky-bucket rate limiting, including their treatment of bursts.
- Discuss caching benefits, invalidation challenges, validators, and privacy risks.
- Explain how SLOs and error budgets can influence release and incident-management decisions.
- Describe a complete performance-testing strategy for a high-traffic REST API.
Analytical / Application Questions- A service receives 40 requests per second and has an average response time of 250 ms. Use Little’s Law to estimate the average number of in-flight requests. State your units and assumptions.
- An API has a 99.9% monthly availability SLO over a 30-day month. Calculate the approximate monthly error budget in minutes, then explain why request-based and time-based definitions may differ.
- Design a resilience strategy for an API whose optional recommendation service frequently times out while its transactional database must remain correct. Identify timeout, retry, bulkhead, circuit-breaker, caching, and observability decisions.
Multiple Choice Questions with AnswersQuestion 1Which HTTP status most appropriately indicates that a client has exceeded a documented request-rate limit? A. 400 Bad Request B. 404 Not Found C. 429 Too Many Requests D. 500 Internal Server Error Correct Answer: C. 429 Too Many Requests Question 2What is the principal purpose of jitter in an exponential-backoff retry policy? A. To make every retry occur immediately B. To prevent synchronized retries from creating a retry storm C. To guarantee that a dependency is available D. To increase the number of permitted retries Correct Answer: B. To prevent synchronized retries from creating a retry storm Question 3A repeated POST request uses the same valid idempotency key and identical payload as an earlier completed request. What should a well-designed service normally do? A. Perform the operation again unconditionally B. Return the previously recorded result C. Return 404 because POST cannot be repeated D. Delete the earlier result Correct Answer: B. Return the previously recorded result Question 4A cache has an 80% hit ratio, 10 ms hit latency, and 110 ms miss latency. What is the expected latency under the two-class model? A. 20 ms B. 30 ms C. 80 ms D. 100 ms Correct Answer: B. 30 ms Question 5Which pattern isolates a failing dependency so that it cannot consume all of a service’s connection or thread capacity? A. Bulkhead B. Content negotiation C. Pagination D. Serialization Correct Answer: A. Bulkhead Question 6Under Little’s Law, a stable system processes 50 requests per second with an average time in the system of 0.2 seconds. What is the average number of in-flight requests? A. 2 B. 10 C. 50 D. 250 Correct Answer: B. 10 Question 7Which statement best distinguishes an SLO from an SLA? A. An SLO is a measured target; an SLA is a contractual commitment B. An SLO is always legally enforceable; an SLA is never contractual C. An SLO measures source code size; an SLA measures CPU usage D. They are identical terms in all contexts Correct Answer: A. An SLO is a measured target; an SLA is a contractual commitment Question 8What is the safest general reason to avoid retrying a validation error such as an invalid field value? A. Validation errors are always caused by network congestion B. Repeating the unchanged invalid request is unlikely to succeed C. Validation errors indicate that the server is overloaded D. Retries can never be used with HTTP Correct Answer: B. Repeating the unchanged invalid request is unlikely to succeed Question 9Which metric is most likely to reveal slow experiences affecting a small but important fraction of users? A. Only mean latency B. p99 latency C. Total number of source files D. Number of API routes Correct Answer: B. p99 latency Question 10What is the principal role of a readiness check in a service deployment? A. To determine whether an instance should receive traffic B. To verify that a user has entered a valid password C. To compress response bodies D. To calculate cache TTL Correct Answer: A. To determine whether an instance should receive traffic
|