Pure Effect
A zero-dependency effect library for JavaScript and TypeScript where business logic returns plain objects describing I/O, enabling testing without mocks and production bug replay.
At a Glance
About Pure Effect
Pure Effect is a zero-dependency effect library for JavaScript and TypeScript, created by Aycan Gulez and released under the MIT license. It solves the problem of tangled business logic and I/O by having functions return plain objects that describe what they would do, rather than executing side effects directly. The library is available on npm and weighs under 1 KB minified and gzipped.
What It Is
Pure Effect is a functional effects-as-data library built around six composable primitives: Success, Failure, Command, Ask, Retry, and Parallel. Instead of writing await db.findUser(email) inside business logic, you return a Command object that describes the call. An interpreter (runEffect) sits at the edge of your system and executes those commands. Because the pipeline is a plain data tree before it runs, you can walk it in a test, assert on its structure, and replay a failed production run without touching any infrastructure.
Six Primitives and How They Compose
The entire API surface is six primitives plus three composer functions:
- Success(value) — wraps a successful result
- Failure(error) — stops the pipeline and short-circuits remaining steps
- Command(cmdFn, nextFn) — describes a deferred side effect as data
- Ask(nextFn) — reads the context object passed to
runEffectfor dependency injection without threading it through every signature - Retry(effect, opts) — wraps any effect with configurable retry, delay, and exponential backoff
- Parallel(effects, next) — runs effect trees concurrently via
Promise.allwith first-failure short-circuiting
effectPipe composes functions sequentially, and runEffect is the interpreter that traverses the tree and executes commands at the system boundary.
Testing and Production Replay
The core value proposition is that pipelines return inert objects you can inspect before anything executes. A test can assert step.cmd.name === 'cmdFindUser' and step.next(null).cmd.name === 'cmdSaveUser' without a database, a mock, or a container. For production debugging, commands and their results can be recorded during a live run and fed back into the same tree locally to retrace the exact execution path — no infrastructure required. Retry configuration is also plain data, so tests can assert on attempts, delay, and backoff values without timers or sleeps.
TypeScript Support and OpenTelemetry
Pure Effect ships bundled .d.ts type definitions and supports full generics. The Effect<T, E, Ctx> type carries three parameters: the success value type, a union of possible error types collected automatically across pipeline steps, and an optional context type enforced at runEffect call sites. For observability, configureEffect exposes lifecycle hooks — onRun, onStep, and onBeforeCommand — that let you wrap workflows in OpenTelemetry spans without modifying domain code. The repository includes a complete OpenTelemetry wiring example.
Positioning vs. Effect-TS and fp-ts
The project's README explicitly positions Pure Effect against Effect-TS (a full functional ecosystem with fibers, streaming, and structured concurrency) and fp-ts (which brings category-theory abstractions like functors and monads). Pure Effect covers a narrower scope — testable pipelines, context injection, retry, and parallel execution — with the stated goal of being learnable in an afternoon. It is designed for request-shaped operations, not background processes or streaming workloads.
Update: v0.8.0
The latest release is v0.8.0, published on May 3, 2026. The repository was created in November 2025 and last updated in June 2026, indicating active early development. The project has 62 GitHub stars and 2 forks as of the last recorded update.
Community Discussions
Be the first to start a conversation about Pure Effect
Share your experience with Pure Effect, ask questions, or help others learn from your insights.
Pricing
Open Source
Fully free and open source under the MIT license. Install via npm with zero dependencies.
- Zero dependencies
- Under 1 KB minified and gzipped
- Six primitives: Success, Failure, Command, Ask, Retry, Parallel
- Full TypeScript support with bundled .d.ts
- OpenTelemetry lifecycle hooks
Capabilities
Key Features
- Zero dependencies, under 1 KB minified and gzipped
- Six primitives: Success, Failure, Command, Ask, Retry, Parallel
- Test async pipelines without mocks, fakes, or containers
- Replay production failures locally without infrastructure
- Built-in retry with configurable attempts, delay, and exponential backoff
- Parallel execution via Promise.all with first-failure short-circuiting
- Dependency injection via Ask without threading context through signatures
- OpenTelemetry lifecycle hooks (onRun, onStep, onBeforeCommand)
- Full TypeScript generics with typed error unions and context types
- Works in JavaScript and TypeScript with bundled .d.ts
- effectPipe for sequential pipeline composition
- runEffect interpreter executes commands at the system boundary
- configureEffect for global retry defaults and telemetry hooks
- Per-call overrides via callConfig in runEffect
