From harness-claude
Implements bulkhead pattern in TypeScript to partition resources, limit concurrency per dependency, and isolate failures from slow components starving others.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Isolate failures by partitioning resources so one failing component cannot exhaust capacity for others
Implements semaphore-based bulkheads in TypeScript to isolate failures in microservices, limiting concurrent calls to slow dependencies and protecting shared resources like thread pools.
Generates Bulkhead pattern for PHP 8.4 with semaphore concurrency limits, thread pool isolation, Redis distribution, and queue strategies for resource isolation. Includes unit tests for API calls, DB pools, CPU work.
Assists implementing circuit breakers, retries, bulkheads, and resilience patterns for fault-tolerant distributed systems.
Share bugs, ideas, or general feedback.
Isolate failures by partitioning resources so one failing component cannot exhaust capacity for others
// utils/bulkhead.ts
export class Bulkhead {
private active = 0;
private queue: Array<{ resolve: () => void; reject: (err: Error) => void }> = [];
constructor(
private readonly maxConcurrent: number,
private readonly maxQueue: number = 100
) {}
async execute<T>(fn: () => Promise<T>): Promise<T> {
await this.acquire();
try {
return await fn();
} finally {
this.release();
}
}
private acquire(): Promise<void> {
if (this.active < this.maxConcurrent) {
this.active++;
return Promise.resolve();
}
if (this.queue.length >= this.maxQueue) {
return Promise.reject(
new BulkheadRejectError(`Bulkhead full: ${this.active} active, ${this.queue.length} queued`)
);
}
return new Promise((resolve, reject) => {
this.queue.push({ resolve, reject });
});
}
private release(): void {
const next = this.queue.shift();
if (next) {
next.resolve();
} else {
this.active--;
}
}
get stats() {
return { active: this.active, queued: this.queue.length };
}
}
export class BulkheadRejectError extends Error {
constructor(message: string) {
super(message);
this.name = 'BulkheadRejectError';
}
}
// services/payment-service.ts
const paymentBulkhead = new Bulkhead(10, 50); // Max 10 concurrent, 50 queued
const notificationBulkhead = new Bulkhead(20, 100);
export async function processPayment(orderId: string): Promise<PaymentResult> {
return paymentBulkhead.execute(() =>
fetch(`https://payment-api.example.com/charge/${orderId}`, { method: 'POST' }).then((r) =>
r.json()
)
);
}
export async function sendNotification(userId: string, message: string): Promise<void> {
return notificationBulkhead.execute(() =>
fetch('https://notification-api.example.com/send', {
method: 'POST',
body: JSON.stringify({ userId, message }),
}).then(() => undefined)
);
}
Types of bulkheads:
Sizing bulkheads: Start with expected_concurrent_requests * 1.5. Monitor rejection rates. If rejections are too high, increase the limit. If the downstream service is overwhelmed, decrease it.
Combining patterns: Bulkhead + circuit breaker + timeout is the resilience trifecta:
async function resilientCall<T>(fn: () => Promise<T>): Promise<T> {
return circuitBreaker.execute(() => bulkhead.execute(() => withTimeout(fn, 5000)));
}
Libraries: cockatiel provides composable bulkhead policy. p-limit is a simpler concurrency limiter. bottleneck adds rate limiting and clustering support.
https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead