High availability means your system remains operational even when components fail. Let's explore the key patterns.
Redundancy
Remove single points of failure:
typescript
class RedundantService {
private instances: Service[] = [];
async call(): Promise<Response> {
// Try primary
try {
return await this.instances[0].execute();
} catch (error) {
// Fallback to backup
return await this.instances[1].execute();
}
}
}Health Checks
Monitor service health:
typescript
class HealthChecker {
async checkService(service: Service): Promise<boolean> {
try {
const response = await fetch(service.healthEndpoint);
return response.ok;
} catch {
return false;
}
}
async checkAll(): Promise<HealthStatus> {
const results = await Promise.all(
this.services.map(async s => ({
service: s.name,
healthy: await this.checkService(s)
}))
);
return { services: results };
}
}Circuit Breakers
Prevent cascading failures:
typescript
class CircuitBreaker {
private failures = 0;
private lastFailureTime = 0;
private state: 'closed' | 'open' | 'half-open' = 'closed';
async execute(fn: () => Promise<any>): Promise<any> {
if (this.state === 'open') {
if (Date.now() - this.lastFailureTime > 60000) {
this.state = 'half-open';
} else {
throw new Error('Circuit breaker is open');
}
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private onSuccess() {
this.failures = 0;
if (this.state === 'half-open') {
this.state = 'closed';
}
}
private onFailure() {
this.failures++;
this.lastFailureTime = Date.now();
if (this.failures >= 5) {
this.state = 'open';
}
}
}Conclusion
High availability requires redundancy, monitoring, and automatic failover.