A one-page argument
Just use Effect.
Effect<Success, Error, Requirements>
Three reasons. Plus a post from the guy who built it.
From the guy who built it
Effect is verbose is an argument that makes no sense, it is verbose compared to code that only cares about the happy path, that is not testable and doesn’t integrate telemetry. Compared to production grade code Effect is terse.
Why
-
Your errors and dependencies are in the type.
Every Effect is
Effect<Success, Error, Requirements>. Don’t handle an error, or forget to provide a service, and it doesn’t compile. APromise<T>tells you none of that. You find out in prod.// what can this throw? what does it need? no idea. getUser: (id: string) => Promise<User> // all of it is right there getUser: (id: UserId) => Effect<User, UserNotFound | DbTimeout, Database>
-
You’re already building Effect, badly.
Retries, timeouts, cancellation, cleanup, config, validation, tracing. Every production codebase has a hand-rolled version of each one, spread across a dozen packages that were never designed to work together. Effect is that code, except finished, and all of it fits together.
-
LLMs write the code now.
The cost of Effect was always learning it and typing it out. The model does both now. Whatever excuse you had before, it’s gone. What’s left is the part the model can’t bluff its way through: a signature the compiler actually checks, so the generated code has to meet a contract before you even read it.
Get started