# Effect TS Concurrency

> Use when performing parallel operations, rate limiting, or signaling between fibers in Effect-TS.

- Skill: `mrevanzak/effect-ts-concurrency` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mrevanzak/effect-ts-concurrency`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mrevanzak/effect-ts-concurrency/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: mrevanzak (https://skillmd.com/u/mrevanzak)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mrevanzak/effect-ts-concurrency

---


# Effect-TS Concurrency

## Overview
Effect-TS provides lightweight fibers for high-performance concurrency. The core principle is **explicit control**: always bound parallelism to prevent resource exhaustion.

## When to Use
- Processing large arrays of effects (e.g., `Effect.all`, `Effect.forEach`)
- Rate limiting external API calls or database connections
- Coordinating work between background processes (fibers)
- Signaling completion or state changes across different parts of the app

**When NOT to use:**
- Simple sequential operations
- When standard `Promise.all` is sufficient (though Effect is usually preferred for consistency)

## Core Pattern: Bounded Parallelism
Unbounded parallelism is the most common source of "Too many open files" or "Connection timeout" errors.

| Pattern | Implementation | Result |
|---------|----------------|--------|
| **BAD** | `Effect.all(effects)` | Unbounded - crashes on large inputs |
| **GOOD** | `Effect.all(effects, { concurrency: 10 })` | Bounded - safe and predictable |

## Quick Reference
| Tool | Purpose | Key Method |
|------|---------|------------|
| **Fiber** | Background execution | `Effect.fork` / `Fiber.join` |
| **Semaphore** | Bounded concurrency / Rate limiting | `semaphore.withPermits(n)` |
| **Deferred** | One-shot signaling / Promises | `Deferred.await` / `Deferred.succeed` |
| **concurrency** | Option for `all`, `forEach`, `mapEffect` | `{ concurrency: number | 'unbounded' }` |

## Implementation

### 1. Bounded Parallelism (Critical)
Always specify concurrency when processing collections.

```typescript
import { Effect } from 'effect';

// Process 1000 items, max 10 concurrent
const results = yield* Effect.all(
  items.map(processItem),
  { concurrency: 10 }
);
```

### 2. Semaphore for Rate Limiting
Use a Semaphore when multiple independent operations must share a global limit.

```typescript
import { Effect } from 'effect';

const program = Effect.gen(function* () {
  const semaphore = yield* Effect.makeSemaphore(5); // Max 5 concurrent
  
  yield* Effect.all(
    requests.map((req) => 
      semaphore.withPermits(1)(handleRequest(req))
    ),
    { concurrency: 'unbounded' } // Semaphore controls actual concurrency
  );
});
```

### 3. Deferred for Signaling
Use Deferred to wait for a specific event or value from another fiber.

```typescript
import { Deferred, Effect, Fiber } from 'effect';

const program = Effect.gen(function* () {
  const signal = yield* Deferred.make<void>();
  
  const worker = yield* Effect.fork(
    Effect.gen(function* () {
      yield* Deferred.await(signal); // Wait for signal
      yield* doWork();
    })
  );
  
  yield* setup();
  yield* Deferred.succeed(signal, undefined); // Trigger worker
  yield* Fiber.join(worker);
});
```

## Common Mistakes
- **Unbounded parallelism:** Forgetting `{ concurrency: n }` in `Effect.all`.
- **Leaking Fibers:** Forking fibers without joining or interrupting them (use `Effect.scoped` for safety).
- **Deadlocks:** Circular dependencies between semaphores or deferreds.

## Red Flags - STOP and Start Over
- Using `Effect.all` on a large array without `{ concurrency: n }`.
- Using `Promise.all` inside an Effect-TS codebase.
- Manual `setTimeout` for rate limiting instead of `Effect.makeRateLimiter` or `Semaphore`.

## Rationalization Table
| Excuse | Reality |
|--------|---------|
| "It's only 100 items" | 100 items today, 10,000 tomorrow. Bound it now. |
| "The API is fast" | Network latency and server load are unpredictable. |
| "I'll add concurrency later" | Unbounded parallelism is a ticking time bomb. |

**REQUIRED BACKGROUND:** See effect-ts-anti-patterns for more on unbounded parallelism.

