Availability means how often a system is operational and accessible when users need it.
Imagine you are using a banking application at 2 AM. You try to check your account balance, but the application is down.
The application may have excellent features, but if users cannot access it, those features are not useful.
This is why availability is an important part of System Design.
What Does Availability Mean?
In simple terms:
Availability = How much of the time the system is available for users.
For example, if an application is available almost all the time but goes down for maintenance or unexpected failures, we measure how much downtime occurred.
Availability is commonly expressed as a percentage.
| Availability | Approximate Yearly Downtime |
|---|---|
| 99% | About 3 days 15 hours |
| 99.9% | About 8 hours 46 minutes |
| 99.99% | About 52 minutes |
| 99.999% | About 5 minutes |
These values show why even a small difference in availability can become significant for systems that operate continuously.
Real-World Example
Consider an online payment system.
The basic architecture might look like:
flowchart LR
User --> API
API --> Database
API --> PaymentService
Now imagine the API server crashes.
If there is only one API server, users may not be able to make payments.
This creates a single point of failure.
Single Point of Failure
A Single Point of Failure is a component whose failure can make the entire system unavailable.
For example:
flowchart LR
User --> API
API --> Database
If the API server fails, the system stops responding.
To improve availability, we can run multiple API servers.
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
LoadBalancer --> API3
If API1 fails, the Load Balancer can continue sending requests to API2 and API3.
ASP.NET Core Example
Suppose we have a simple ASP.NET Core API:
[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult GetOrder(int id)
{
return Ok(new
{
Id = id,
Status = "Confirmed"
});
}
}
We can run the same application on multiple servers.
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
LoadBalancer --> API3
All three servers can run the same ASP.NET Core application.
If one server becomes unavailable, the other servers can continue serving requests.
What About the Database?
Having multiple API servers is not enough.
Suppose we have three API servers but only one database:
flowchart LR
LoadBalancer --> API1
LoadBalancer --> API2
LoadBalancer --> API3
API1 --> Database
API2 --> Database
API3 --> Database
If the database becomes unavailable, all three API servers may be unable to retrieve or store data.
The database has now become a critical dependency.
This is why availability needs to be considered across the complete system, not just the application layer.
Database High Availability
SQL Server environments can use different high-availability and disaster-recovery approaches depending on the requirements.
At a high level, we can have a primary database and another database that can take over when required.
flowchart LR
API --> PrimaryDatabase
PrimaryDatabase --> SecondaryDatabase
The exact SQL Server technology and topology depend on factors such as recovery requirements, infrastructure and application workload.
Availability Through Redundancy
Redundancy means having additional resources available so that the failure of one resource does not necessarily stop the entire system.
For example:
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
API1 --> Database
API2 --> Database
Here, API1 and API2 provide redundancy at the application layer.
If API1 fails, API2 can continue processing requests.
Health Checks
How does the Load Balancer know that an API server is unhealthy?
Usually, the application exposes a health-check endpoint.
For example:
app.MapGet("/health", () =>
{
return Results.Ok(new
{
status = "Healthy"
});
});
The infrastructure can periodically call this endpoint.
flowchart LR
LoadBalancer --> HealthCheck
HealthCheck --> API1
HealthCheck --> API2
If API1 stops responding correctly, the Load Balancer can stop sending normal traffic to that instance.
Availability and Database Failures
Consider an order API:
[HttpPost]
public async Task CreateOrder(Order order)
{
_context.Orders.Add(order);
await _context.SaveChangesAsync();
return Ok(order);
}
If SQL Server is unavailable, SaveChangesAsync will fail.
Therefore, the API cannot guarantee that the order has been stored.
This is an important point:
Availability is about the complete request path, not just whether the API server is running.
Availability During Deployment
Another real-world problem is deployment.
Suppose we have only one API server and we deploy a new version.
The server may need to stop temporarily.
During that time, users may receive errors.
With multiple instances, we can update instances without taking the complete application offline.
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
API1 --> Database
API2 --> Database
For example, API1 can be updated while API2 continues serving traffic. Then API1 can return to service and API2 can be updated.
The exact deployment strategy depends on the infrastructure and platform.
Availability vs Scalability
These concepts are related but different.
Scalability asks:
Can the system handle increasing workload?
Availability asks:
Can users access the system when they need it?
Multiple servers can help with both, but the goals are different.
Simple Example
Imagine an application with three API servers.
Normally:
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API2
LoadBalancer --> API3
If API2 fails:
flowchart LR
User --> LoadBalancer
LoadBalancer --> API1
LoadBalancer --> API3
The system can continue serving users through the remaining healthy servers.
This is the basic idea behind improving availability through redundancy.
Important Questions in System Design
When discussing availability, ask:
- What happens if an API server fails?
- What happens if the database fails?
- Is there a single point of failure?
- How do we detect unhealthy instances?
- How do we recover from failures?
- Can we deploy without taking the application completely offline?
- What happens if an entire infrastructure location becomes unavailable?
Key Takeaways
- Availability means the system is accessible when users need it.
- Availability is commonly measured as a percentage.
- A Single Point of Failure can make an entire system unavailable.
- Redundant application servers can improve availability.
- Health checks help detect unhealthy instances.
- The database and other dependencies must also be considered.
- Availability should be designed across the complete request path.
Conclusion
A system is not highly available simply because the application is running.
We need to consider every important component involved in processing a request: application servers, databases, caches, external services and infrastructure.
By removing single points of failure, adding redundancy and detecting failures quickly, we can build systems that continue serving users even when individual components fail.
But availability alone is not enough. A system can be available and still produce incorrect results or fail intermittently.
That brings us to the next concept: Reliability.