Availability in System Design
In system design, availability means how much of the time a system is up and working when users want to use it. If a system is available, users can open it, send requests and get correct answers without errors. In simple words, availability answers one question: "Is the system working right now?"
This tutorial explains how availability is measured, what the famous "nines" mean, how to calculate the availability of a whole system, what causes downtime, and the proven techniques that keep systems running, with simple Java examples.
1. What Is Availability?
Availability is usually written as a percentage of time. A system with 99.9% availability is working 99.9% of the time and is unavailable for the remaining 0.1%.
A system is highly available when it keeps working even if some of its parts fail. This is usually achieved by removing single points of failure: parts whose failure would bring the whole system down.
2. Why Availability Is Important
Users expect applications to work at any time, from anywhere. When a system is down:
- Revenue is lost: an online store that is down cannot take orders, especially painful during a sale.
- Trust is damaged: users who find a service broken may move to a competitor.
- Productivity drops: employees who rely on internal tools cannot work.
- Contracts may be broken: many services promise a minimum uptime and must pay penalties if they miss it.
- Safety can be at risk: in healthcare, transport or banking, downtime can have serious consequences.
This is why availability is one of the most important non-functional requirements in system design.
3. How Availability Is Measured
The Basic Formula
Availability = Uptime / (Uptime + Downtime)
Example: a 30-day month has 720 hours. If the system is down for 1 hour:
Uptime = 720 - 1 = 719 hours
Availability = 719 / 720 = 0.99861 -> about 99.86%
Using MTBF and MTTR
Engineers also describe availability with two averages:
- MTBF (Mean Time Between Failures): how long the system runs, on average, before it fails.
- MTTR (Mean Time To Repair/Recover): how long it takes, on average, to get it working again.
Availability = MTBF / (MTBF + MTTR)
Example: MTBF = 500 hours, MTTR = 1 hour
Availability = 500 / 501 ≈ 0.998 -> about 99.8%
This formula shows the two ways to improve availability: fail less often (higher MTBF) or recover faster (lower MTTR). In practice, automatic recovery that cuts MTTR from hours to seconds is often the biggest win.
4. The "Nines" of Availability
Availability targets are often described by their number of nines. Each extra nine cuts the allowed downtime by ten times:
| Availability | Downtime per Year | Downtime per Month | Downtime per Day |
|---|---|---|---|
| 99% (two nines) | About 3.65 days | About 7.3 hours | About 14.4 minutes |
| 99.9% (three nines) | About 8.77 hours | About 43.8 minutes | About 1.4 minutes |
| 99.99% (four nines) | About 52.6 minutes | About 4.4 minutes | About 8.6 seconds |
| 99.999% (five nines) | About 5.3 minutes | About 26 seconds | Under 1 second |
Each extra nine is much harder and more expensive to reach. Most web applications aim for 99.9% or 99.99%; five nines is usually reserved for critical systems such as telecom networks and payment infrastructure.
5. Availability of a Whole System
A real system is made of many parts. How they are connected changes the overall availability.
Components in Series
When a request must pass through every component (load balancer → app server → database), all of them must work. Multiply their availabilities:
A(total) = A1 x A2 x A3
Load balancer 99.99% x App server 99.9% x Database 99.9%
= 0.9999 x 0.999 x 0.999 ≈ 0.9979 -> about 99.79%
The whole system is less available than its weakest part. Every extra dependency in the chain lowers the total.
Components in Parallel
When there are several identical copies and only one needs to work, the system fails only if all copies fail at the same time:
A(total) = 1 - (1 - A) ^ n
Two app servers, each 99.9%:
= 1 - (0.001 x 0.001) = 0.999999 -> 99.9999%
This is why redundancy is so powerful: two ordinary servers together are far more available than one excellent server. (This assumes the copies fail independently; if both run in the same data centre and it loses power, they fail together.)
6. SLA, SLO and SLI
| Term | Meaning | Example |
|---|---|---|
| SLI (Service Level Indicator) | What you actually measure | Percentage of successful requests in the last 30 days |
| SLO (Service Level Objective) | The internal target for that measurement | 99.95% of requests succeed each month |
| SLA (Service Level Agreement) | A promise to customers, often with penalties | 99.9% uptime, or customers get a 10% credit |
Teams usually set the SLO stricter than the SLA, so they get a warning before a customer promise is broken. The gap between 100% and the SLO is called the error budget: the amount of failure the team can "spend" on risky changes such as new releases.
7. Common Causes of Downtime
- Hardware failures: disks, servers, power supplies or network cards stop working.
- Software bugs: crashes, memory leaks or infinite loops.
- Bad deployments: a new release or configuration change breaks something; this is one of the most common causes.
- Overload: sudden traffic spikes exhaust CPU, memory, threads or database connections.
- Network problems: lost connectivity, DNS errors or expired certificates.
- Dependency failures: a database, payment provider or other service is down, and the failure spreads.
- Human error: a wrong command, a deleted table or a misconfigured firewall.
- Disasters: a power outage, fire or flood takes out a whole data centre.
- Planned maintenance: upgrades that need the system to be stopped.
8. How to Improve Availability
- Redundancy: Run at least two copies of every important component (servers, databases, load balancers) so one can fail without stopping the system.
- Load Balancing with Health Checks: Spread traffic across servers and stop sending requests to any server that fails its health check. See Load Balancing.
- Failover: Automatically switch to a backup when the main component fails.
- Data Replication: Keep copies of the database on other servers so data is still reachable if one server goes down.
- Multiple Zones and Regions: Spread servers across separate data centres (availability zones) and, for critical systems, across geographic regions.
- Graceful Degradation: When a non-critical feature fails, hide it or show a simple default instead of failing the whole page.
- Timeouts, Retries and Circuit Breakers: Stop one slow dependency from blocking everything else.
- Rate Limiting and Auto-Scaling: Protect the system from overload and add capacity automatically when traffic grows.
- Zero-Downtime Deployments: Use rolling, blue-green or canary releases so updates never require taking the system offline.
- Monitoring and Alerting: Detect problems quickly, often before users notice, and alert the on-call engineer.
- Backups and Disaster Recovery: Regularly back up data and practise restoring it.
Active-Passive vs Active-Active Failover
| Aspect | Active-Passive | Active-Active |
|---|---|---|
| How it works | One node serves traffic; a standby takes over if it fails | All nodes serve traffic at the same time |
| Failover time | Seconds to minutes while the standby takes over | Almost instant; others keep serving |
| Resource use | Standby is mostly idle | All capacity is used |
| Complexity | Simpler, especially for databases | Harder; data must stay in sync across nodes |
| Typical use | Primary database with a replica | Stateless web and application servers |
Disaster Recovery: RTO and RPO
- RTO (Recovery Time Objective): the maximum acceptable time to restore service after a disaster, for example 1 hour.
- RPO (Recovery Point Objective): the maximum acceptable amount of data loss, measured in time, for example the last 5 minutes of data.
9. Example: A Highly Available Online Store
Imagine an online shopping website where customers browse products, place orders and pay. If the site goes down during a big sale, customers cannot buy anything and the business loses money. Here is how the system can be designed to stay up:
Users
|
v
[ DNS with health checks ]
|
+-----------+-----------+
| |
Availability Zone A Availability Zone B
| |
[ Load Balancer A ] [ Load Balancer B ]
| |
App Server 1, 2 App Server 3, 4
| |
[ Primary DB ] -- replication --> [ Replica DB ]
(automatic failover if the primary fails)
- Multiple servers instead of one: four app servers across two zones; any of them can handle any request.
- Automatic traffic redirection: load balancers remove unhealthy servers, and DNS can send users away from a failed zone.
- Replicated database: the replica is promoted to primary if the primary fails, so data stays reachable.
- Graceful degradation: if the recommendation service is down, the product page shows best sellers instead of an error.
- Safe releases: new versions roll out to one server at a time and are rolled back automatically if errors rise.
Because of this setup, even if a server, a database or a whole data centre fails, the store keeps working. This makes the system highly available.
10. Availability Techniques in Java
Calculating System Availability
This small utility applies the series and parallel formulas from section 5 to compare a design without and with redundancy:
public final class AvailabilityCalculator {
private static final double HOURS_PER_YEAR = 365 * 24; // 8,760 hours
private AvailabilityCalculator() {
}
/** Every component must work, so availabilities are multiplied. */
public static double inSeries(double... availabilities) {
double result = 1.0;
for (double availability : availabilities) {
result *= availability;
}
return result;
}
/** At least one of the identical copies must work. */
public static double inParallel(double availability, int copies) {
return 1.0 - Math.pow(1.0 - availability, copies);
}
public static double downtimeHoursPerYear(double availability) {
return (1.0 - availability) * HOURS_PER_YEAR;
}
public static void main(String[] args) {
// Load balancer 99.99%, one app server 99.9%, one database 99.9%
double single = inSeries(0.9999, 0.999, 0.999);
// Same design, but with two app servers and two databases
double redundant = inSeries(0.9999, inParallel(0.999, 2), inParallel(0.999, 2));
System.out.printf("Single copies : %.4f%% (%.1f hours down per year)%n",
single * 100, downtimeHoursPerYear(single));
System.out.printf("With redundancy: %.4f%% (%.1f hours down per year)%n",
redundant * 100, downtimeHoursPerYear(redundant));
}
}
Single copies : 99.7901% (18.4 hours down per year)
With redundancy: 99.9898% (0.9 hours down per year)
Adding a second app server and a database replica cuts the expected downtime from about 18 hours to less than one hour per year. The load balancer is now the weakest link, so it should be made redundant too.
Health Checks with Spring Boot Actuator
Load balancers and Kubernetes decide whether to send traffic to an instance by calling its health endpoint. Spring Boot Actuator provides one, and you can add your own checks:
management:
endpoints:
web:
exposure:
include: health
endpoint:
health:
probes:
enabled: true # adds /actuator/health/liveness and /actuator/health/readiness
show-details: always # show component details (restrict this in production)
package com.javabytechie.store.health;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final PaymentGatewayClient paymentGatewayClient;
public PaymentGatewayHealthIndicator(PaymentGatewayClient paymentGatewayClient) {
this.paymentGatewayClient = paymentGatewayClient;
}
@Override
public Health health() {
long start = System.currentTimeMillis();
try {
paymentGatewayClient.ping();
return Health.up()
.withDetail("responseTimeMs", System.currentTimeMillis() - start)
.build();
} catch (Exception ex) {
return Health.down(ex).build();
}
}
}
Calling GET /actuator/health now includes a paymentGateway entry. Keep external dependencies out of the liveness check; otherwise a payment provider outage could make Kubernetes restart healthy servers.
Failover: Try the Primary, Then the Backup
This simple client tries each endpoint in order and returns the first successful answer:
import java.util.List;
import java.util.function.Supplier;
public class FailoverClient<T> {
private final List<Supplier<T>> endpoints; // in priority order: primary first
public FailoverClient(List<Supplier<T>> endpoints) {
if (endpoints.isEmpty()) {
throw new IllegalArgumentException("At least one endpoint is required");
}
this.endpoints = List.copyOf(endpoints);
}
public T call() {
RuntimeException lastError = null;
for (Supplier<T> endpoint : endpoints) {
try {
return endpoint.get();
} catch (RuntimeException ex) {
lastError = ex; // remember the error and try the next endpoint
}
}
throw new IllegalStateException("All endpoints failed", lastError);
}
public static void main(String[] args) {
FailoverClient<String> client = new FailoverClient<>(List.of(
() -> { throw new RuntimeException("Primary is down"); },
() -> "Response from backup server"));
System.out.println(client.call()); // prints: Response from backup server
}
}
Graceful Degradation with a Fallback
With Resilience4j, a failing recommendation service does not break the product page; customers simply see best sellers instead:
package com.javabytechie.store.recommendation;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import java.util.List;
import org.springframework.stereotype.Service;
@Service
public class RecommendationService {
private final RecommendationClient recommendationClient;
private final BestSellerCache bestSellerCache;
public RecommendationService(RecommendationClient recommendationClient,
BestSellerCache bestSellerCache) {
this.recommendationClient = recommendationClient;
this.bestSellerCache = bestSellerCache;
}
@CircuitBreaker(name = "recommendations", fallbackMethod = "bestSellers")
public List<Product> recommendFor(String customerId) {
return recommendationClient.fetchRecommendations(customerId);
}
// Used when the call fails or the circuit is open: a simpler, but still useful, answer.
private List<Product> bestSellers(String customerId, Throwable ex) {
return bestSellerCache.topTen();
}
}
Learn more in the Circuit Breaker Pattern tutorial.
11. Availability vs Reliability vs Durability
These three terms are related but not the same:
| Term | Question It Answers | Measured By |
|---|---|---|
| Availability | Is the system up and responding right now? | Percentage of uptime, e.g. 99.9% |
| Reliability | Does it keep working correctly without failing? | MTBF, failure rate, error rate |
| Durability | Is stored data safe from being lost? | Chance of losing data, e.g. 99.999999999% |
Availability depends on both how rarely a system fails (reliability) and how quickly it recovers (MTTR). A system that fails now and then but recovers in seconds can still be highly available. A system can also be up but unreliable, for example when it responds quickly with wrong results. See Reliability in System Design.
12. Trade-offs of High Availability
- Cost: extra servers, zones and regions cost money, and each additional nine costs more than the last.
- Complexity: replication, failover and multi-region setups are harder to build, test and operate.
- Consistency: during a network failure, a system that keeps answering may return slightly outdated data. This is the trade-off described by the CAP theorem; see Consistency in System Design.
- Latency: keeping data in sync across distant regions can make writes slower.
Choose the availability target that the business actually needs, not the highest possible number.
13. Best Practices
- Set a clear availability target (SLO) based on business needs.
- Find and remove every single point of failure.
- Run at least two instances of every service, in different availability zones.
- Keep application servers stateless so any instance can handle any request.
- Use health checks and automatic failover instead of manual steps.
- Protect calls to dependencies with timeouts, retries and circuit breakers.
- Release changes gradually and make rollbacks fast and automatic.
- Monitor from the user's point of view and alert on symptoms, not just causes.
- Back up data regularly and actually test restoring it.
- Practise failures (chaos testing) so recovery works when it is really needed.
14. Summary
Availability in system design describes how consistently a system is accessible to its users. It is measured as a percentage of uptime and often expressed in "nines". Components connected in series lower overall availability, while redundant components in parallel raise it dramatically. Highly available systems combine redundancy, load balancing with health checks, automatic failover, replication across zones, graceful degradation, safe deployments and strong monitoring. Designing for availability is essential for modern applications, where users expect services to work anytime and anywhere.
Frequently Asked Questions (FAQ)
Q1. What is availability in system design?
Availability is the percentage of time a system is up and able to serve users correctly. A system with 99.9% availability is working 99.9% of the time and down for at most 0.1% of the time.
Q2. How do you calculate availability?
Divide uptime by total time:
Availability = Uptime / (Uptime + Downtime)
Availability = MTBF / (MTBF + MTTR)
Both formulas give the fraction of time the system is working.
Q3. What does "high availability" mean?
High availability (HA) means a system is designed to keep working even when some of its parts fail, usually reaching 99.9% availability or higher. It is achieved through redundancy, automatic failover and removing single points of failure.
Q4. What are the "nines" of availability?
They are a short way of describing availability targets: 99.9% is "three nines" and 99.99% is "four nines". Each extra nine reduces the allowed downtime by ten times, for example from about 8.77 hours a year to about 52.6 minutes a year.
Q5. How much downtime does 99.9% availability allow?
About 8.77 hours per year, about 43.8 minutes per month, or about 1.4 minutes per day.
Q6. What is a single point of failure?
It is any component whose failure stops the entire system, such as a single database server or a single load balancer. Removing single points of failure through redundancy is the first step towards high availability.
Q7. What is the difference between availability and reliability?
Reliability is about how rarely a system fails and whether it works correctly. Availability is about whether it is up right now, which depends on both how often it fails and how quickly it recovers. A system can be highly available even with occasional failures if recovery is fast.
Q8. What are MTBF and MTTR?
MTBF (Mean Time Between Failures) is the average time a system runs before failing. MTTR (Mean Time To Repair/Recover) is the average time needed to restore it. Higher MTBF and lower MTTR both increase availability.
Q9. How does redundancy improve availability?
With two or more copies of a component, the system fails only if all copies fail at the same time. Two servers that are each 99.9% available give about 99.9999% together, as long as they fail independently.
Q10. Why does adding more components in a chain reduce availability?
When a request needs every component to work, their availabilities are multiplied. For example, 99.9% x 99.9% x 99.9% is only about 99.7%. Each extra required dependency is another thing that can fail.
Q11. What is failover?
Failover is automatically switching to a backup component when the main one fails, for example promoting a replica database to primary. Good failover is automatic and fast, so users barely notice the problem.
Q12. What is the difference between active-active and active-passive?
In active-passive, one node handles traffic while a standby waits to take over. In active-active, all nodes handle traffic at the same time, so losing one simply spreads its load across the others. Active-active fails over faster but is more complex for stateful systems.
Q13. What are SLA, SLO and SLI?
- SLI: the metric you measure, such as the percentage of successful requests.
- SLO: your internal target for that metric, such as 99.95%.
- SLA: a promise to customers, often with financial penalties, such as 99.9%.
Q14. What is an error budget?
It is the amount of unreliability allowed by your SLO. With a 99.9% monthly SLO, you can "spend" about 43.8 minutes of failure per month. If the budget is used up, teams usually slow down risky releases and focus on stability.
Q15. How do health checks help availability?
Load balancers and orchestrators such as Kubernetes regularly call a health endpoint on each instance. If an instance stops responding correctly, it is removed from traffic or restarted automatically, which reduces recovery time.
Q16. What is graceful degradation?
It means that when a non-essential feature fails, the system keeps its core functions working and offers a simpler result, for example showing best sellers when personalised recommendations are unavailable, instead of showing an error page.
Q17. How can software be deployed without downtime?
Use rolling deployments (update servers one at a time), blue-green deployments (switch traffic from the old environment to a new one) or canary releases (send a small share of traffic to the new version first). Each allows quick rollback if something goes wrong.
Q18. What are RTO and RPO?
RTO (Recovery Time Objective) is how quickly service must be restored after a disaster. RPO (Recovery Point Objective) is how much recent data you can afford to lose. For example, an RTO of 1 hour and an RPO of 5 minutes.
Q19. Does high availability conflict with consistency?
Sometimes. According to the CAP theorem, when a network partition happens, a distributed system must choose between staying available and keeping every read fully up to date. Many systems choose availability and accept eventual consistency for non-critical data.
Q20. Should every system aim for 99.999% availability?
No. Each extra nine is much more expensive and complex to achieve. Pick a target based on what downtime really costs the business: 99.9% is enough for many internal tools, while payment or emergency systems may justify 99.99% or more.