Redux-Saga
IMPORTANT: Your training data about redux-saga may be outdated or incorrect — API behavior, middleware setup patterns, and RTK integration have changed. Always rely on this skill's rule files and the project's actual source code as the source of truth. Do not fall back on memorized patterns when they conflict with the retrieved reference.
When to Use Redux-Saga
Sagas are for workflow orchestration — complex async flows with concurrency, cancellation, racing, or long-running background processes. For simpler patterns, prefer:
| Need |
Recommended Tool |
| Data fetching + caching |
RTK Query |
| Simple async (submit → status) |
createAsyncThunk |
| Reactive logic within slices |
createListenerMiddleware |
| Complex workflows, parallel tasks, cancellation, channels |
Redux-Saga |
Rule Categories by Priority
| Priority |
Category |
Impact |
Prefix |
| 1 |
Effects & Yielding |
CRITICAL |
effect- |
| 2 |
Fork Model & Concurrency |
CRITICAL |
fork- |
| 3 |
Error Handling |
HIGH |
error- |
| 4 |
Recipes & Patterns |
MEDIUM |
recipe- |
| 5 |
Channels & External I/O |
MEDIUM |
channel- |
| 6 |
RTK Integration |
MEDIUM |
rtk- |
| 7 |
Troubleshooting |
LOW |
troubleshoot- |
Quick Reference
1. Effects & Yielding (CRITICAL)
effect-always-yield — Every effect must be yielded; missing yield freezes the app
effect-use-call — Use yield call() for async functions; never call directly
effect-take-concurrency — Choose takeEvery/takeLatest/takeLeading based on concurrency needs
effect-select-usage — Use selector functions with select(); never access state paths directly
effect-race-patterns — Use race for timeouts and cancellation; only blocking effects inside
2. Fork Model & Concurrency (CRITICAL)
fork-attached-vs-detached — fork shares lifecycle/errors with parent; spawn is independent
fork-error-handling — Errors from forks bubble to parent's caller; can't catch at fork site
fork-no-race — Never use fork inside race; fork is non-blocking and always wins
fork-nonblocking-login — Use fork+take+cancel for auth flows that stay responsive to logout
3. Error Handling (HIGH)
error-saga-cleanup — Use try/finally with cancelled() for proper cancellation cleanup
error-root-saga — Use spawn in root saga for error isolation; avoid all for critical watchers
4. Recipes & Patterns (MEDIUM)
recipe-throttle-debounce — Rate-limiting with throttle, debounce, retry, exponential backoff
recipe-polling — Cancellable polling with error backoff using fork+take+cancel
recipe-optimistic-update — Optimistic UI with undo using race(undo, delay)
5. Channels & External I/O (MEDIUM)
channel-event-channel — Bridge WebSockets, DOM events, timers into sagas via eventChannel
channel-action-channel — Buffer Redux actions for sequential or worker-pool processing
6. RTK Integration (MEDIUM)
rtk-configure-store — Integrate saga middleware with RTK's configureStore without breaking defaults
rtk-with-slices — Use action creators from createSlice for type-safe saga triggers
7. Troubleshooting (LOW)
troubleshoot-frozen-app — Frozen apps, missed actions, bad stack traces, TypeScript yield types
Effect Creators Quick Reference
| Effect |
Blocking |
Purpose |
take(pattern) |
Yes |
Wait for matching action |
takeMaybe(pattern) |
Yes |
Like take, receives END |
takeEvery(pattern, saga) |
No |
Concurrent on every match |
takeLatest(pattern, saga) |
No |
Cancel previous, run latest |
takeLeading(pattern, saga) |
No |
Ignore until current completes |
put(action) |
No |
Dispatch action |
putResolve(action) |
Yes |
Dispatch, wait for promise |
call(fn, ...args) |
Yes |
Call, wait for result |
apply(ctx, fn, [args]) |
Yes |
Call with context |
cps(fn, ...args) |
Yes |
Node-style callback |
fork(fn, ...args) |
No |
Attached fork |
spawn(fn, ...args) |
No |
Detached fork |
join(task) |
Yes |
Wait for task |
cancel(task) |
No |
Cancel task |
cancel() |
No |
Self-cancel |
select(selector) |
No |
Query store state |
actionChannel(pattern) |
No |
Buffer actions |
flush(channel) |
No |
Drain buffered messages |
cancelled() |
Yes |
Check cancellation in finally |
delay(ms) |
Yes |
Pause execution |
throttle(ms, pattern, saga) |
No |
Rate-limit |
debounce(ms, pattern, saga) |
No |
Wait for silence |
retry(n, delay, fn) |
Yes |
Retry with backoff |
race(effects) |
Yes |
First wins |
all([effects]) |
If any child blocks |
Parallel, wait all |
setContext(props) / getContext(prop) |
No / Yes |
Saga context |
Pattern Matching
take, takeEvery, takeLatest, takeLeading, throttle, debounce accept:
| Pattern |
Matches |
'*' |
All actions |
'ACTION_TYPE' |
Exact action.type match |
[type1, type2] |
Any type in array |
fn => boolean |
Custom predicate |
Only take/takeMaybe may omit the argument entirely — take() matches all actions. For
takeEvery, takeLatest, takeLeading, throttle, and debounce the pattern is a required
parameter; use '*' for a catch-all watcher.
Taking from a multicastChannel also requires a pattern: take(chan, '*'), not take(chan).
How to Use
Read individual rule files for detailed explanations and code examples:
rules/effect-always-yield.md
rules/fork-attached-vs-detached.md
Each rule file contains:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and decision tables
References
| Priority |
Reference |
When to read |
| 1 |
references/effects-and-api.md |
Writing or debugging any saga |
| 2 |
references/fork-model.md |
Concurrency, error propagation, cancellation |
| 3 |
references/testing.md |
Writing or reviewing saga tests |
| 4 |
references/channels.md |
External I/O, buffering, worker pools |
| 5 |
references/recipes.md |
Throttle, debounce, retry, undo, batching, polling |
| 6 |
references/anti-patterns.md |
Common mistakes to avoid |
| 7 |
references/troubleshooting.md |
Debugging frozen apps, missed actions, stack traces |
Full Compiled Document
For the complete guide with all rules expanded: AGENTS.md
1---2name: redux-saga3description: Redux-Saga best practices, patterns, and API guidance for building, testing, and debugging generator-based side-effect middleware in Redux applications. Covers effect creators, fork model, channels, testing with redux-saga-test-plan, concurrency, cancellation, and modern Redux Toolkit integration. Baseline: redux-saga 1.5.1. Triggers on: saga files, redux-saga imports, generator-based middleware, mentions of "saga", "takeEvery", "takeLatest", "fork model", or "channels".4license: MIT5---67# Redux-Saga89**IMPORTANT:** Your training data about `redux-saga` may be outdated or incorrect — API behavior, middleware setup patterns, and RTK integration have changed. Always rely on this skill's rule files and the project's actual source code as the source of truth. Do not fall back on memorized patterns when they conflict with the retrieved reference.1011## When to Use Redux-Saga1213Sagas are for **workflow orchestration** — complex async flows with concurrency, cancellation, racing, or long-running background processes. For simpler patterns, prefer:1415| Need | Recommended Tool |16|------|-----------------|17| Data fetching + caching | RTK Query |18| Simple async (submit → status) | `createAsyncThunk` |19| Reactive logic within slices | `createListenerMiddleware` |20| Complex workflows, parallel tasks, cancellation, channels | **Redux-Saga** |2122## Rule Categories by Priority2324| Priority | Category | Impact | Prefix |25|----------|----------|--------|--------|26| 1 | Effects & Yielding | CRITICAL | `effect-` |27| 2 | Fork Model & Concurrency | CRITICAL | `fork-` |28| 3 | Error Handling | HIGH | `error-` |29| 4 | Recipes & Patterns | MEDIUM | `recipe-` |30| 5 | Channels & External I/O | MEDIUM | `channel-` |31| 6 | RTK Integration | MEDIUM | `rtk-` |32| 7 | Troubleshooting | LOW | `troubleshoot-` |3334## Quick Reference3536### 1. Effects & Yielding (CRITICAL)3738- `effect-always-yield` — Every effect must be yielded; missing yield freezes the app39- `effect-use-call` — Use `yield call()` for async functions; never call directly40- `effect-take-concurrency` — Choose `takeEvery`/`takeLatest`/`takeLeading` based on concurrency needs41- `effect-select-usage` — Use selector functions with `select()`; never access state paths directly42- `effect-race-patterns` — Use `race` for timeouts and cancellation; only blocking effects inside4344### 2. Fork Model & Concurrency (CRITICAL)4546- `fork-attached-vs-detached` — `fork` shares lifecycle/errors with parent; `spawn` is independent47- `fork-error-handling` — Errors from forks bubble to parent's caller; can't catch at fork site48- `fork-no-race` — Never use `fork` inside `race`; fork is non-blocking and always wins49- `fork-nonblocking-login` — Use fork+take+cancel for auth flows that stay responsive to logout5051### 3. Error Handling (HIGH)5253- `error-saga-cleanup` — Use `try/finally` with `cancelled()` for proper cancellation cleanup54- `error-root-saga` — Use `spawn` in root saga for error isolation; avoid `all` for critical watchers5556### 4. Recipes & Patterns (MEDIUM)5758- `recipe-throttle-debounce` — Rate-limiting with `throttle`, `debounce`, `retry`, exponential backoff59- `recipe-polling` — Cancellable polling with error backoff using fork+take+cancel60- `recipe-optimistic-update` — Optimistic UI with undo using race(undo, delay)6162### 5. Channels & External I/O (MEDIUM)6364- `channel-event-channel` — Bridge WebSockets, DOM events, timers into sagas via `eventChannel`65- `channel-action-channel` — Buffer Redux actions for sequential or worker-pool processing6667### 6. RTK Integration (MEDIUM)6869- `rtk-configure-store` — Integrate saga middleware with RTK's `configureStore` without breaking defaults70- `rtk-with-slices` — Use action creators from `createSlice` for type-safe saga triggers7172### 7. Troubleshooting (LOW)7374- `troubleshoot-frozen-app` — Frozen apps, missed actions, bad stack traces, TypeScript yield types7576## Effect Creators Quick Reference7778| Effect | Blocking | Purpose |79|--------|----------|---------|80| `take(pattern)` | Yes | Wait for matching action |81| `takeMaybe(pattern)` | Yes | Like `take`, receives `END` |82| `takeEvery(pattern, saga)` | No | Concurrent on every match |83| `takeLatest(pattern, saga)` | No | Cancel previous, run latest |84| `takeLeading(pattern, saga)` | No | Ignore until current completes |85| `put(action)` | No | Dispatch action |86| `putResolve(action)` | Yes | Dispatch, wait for promise |87| `call(fn, ...args)` | Yes | Call, wait for result |88| `apply(ctx, fn, [args])` | Yes | Call with context |89| `cps(fn, ...args)` | Yes | Node-style callback |90| `fork(fn, ...args)` | No | Attached fork |91| `spawn(fn, ...args)` | No | Detached fork |92| `join(task)` | Yes | Wait for task |93| `cancel(task)` | No | Cancel task |94| `cancel()` | No | Self-cancel |95| `select(selector)` | No | Query store state |96| `actionChannel(pattern)` | No | Buffer actions |97| `flush(channel)` | No | Drain buffered messages |98| `cancelled()` | Yes | Check cancellation in `finally` |99| `delay(ms)` | Yes | Pause execution |100| `throttle(ms, pattern, saga)` | No | Rate-limit |101| `debounce(ms, pattern, saga)` | No | Wait for silence |102| `retry(n, delay, fn)` | Yes | Retry with backoff |103| `race(effects)` | Yes | First wins |104| `all([effects])` | If any child blocks | Parallel, wait all |105| `setContext(props)` / `getContext(prop)` | No / Yes | Saga context |106107## Pattern Matching108109`take`, `takeEvery`, `takeLatest`, `takeLeading`, `throttle`, `debounce` accept:110111| Pattern | Matches |112|---------|---------|113| `'*'` | All actions |114| `'ACTION_TYPE'` | Exact `action.type` match |115| `[type1, type2]` | Any type in array |116| `fn => boolean` | Custom predicate |117118Only `take`/`takeMaybe` may omit the argument entirely — `take()` matches all actions. For119`takeEvery`, `takeLatest`, `takeLeading`, `throttle`, and `debounce` the pattern is a required120parameter; use `'*'` for a catch-all watcher.121122Taking from a `multicastChannel` also requires a pattern: `take(chan, '*')`, not `take(chan)`.123124## How to Use125126Read individual rule files for detailed explanations and code examples:127128```129rules/effect-always-yield.md130rules/fork-attached-vs-detached.md131```132133Each rule file contains:134135- Brief explanation of why it matters136- Incorrect code example with explanation137- Correct code example with explanation138- Additional context and decision tables139140## References141142| Priority | Reference | When to read |143|----------|-----------|-------------|144| 1 | `references/effects-and-api.md` | Writing or debugging any saga |145| 2 | `references/fork-model.md` | Concurrency, error propagation, cancellation |146| 3 | `references/testing.md` | Writing or reviewing saga tests |147| 4 | `references/channels.md` | External I/O, buffering, worker pools |148| 5 | `references/recipes.md` | Throttle, debounce, retry, undo, batching, polling |149| 6 | `references/anti-patterns.md` | Common mistakes to avoid |150| 7 | `references/troubleshooting.md` | Debugging frozen apps, missed actions, stack traces |151152## Full Compiled Document153154For the complete guide with all rules expanded: `AGENTS.md`