Effect is ramping-up. Like a lot, with AI agents helping 🚀
The Effect-ification of the typescript ecosystem has begun
import { OpenCode } from "@opencode-ai/core/effect"
The agents love Effect!
What the what... We added 1.7m weekly downloads in 6 days, who adopted Effect?
I am already on the other side, where (nearly) everything in my codebases is based on effect ⚡️
Here is how your future looks like if you go effect 👇
Effect end to end
The major win is when effect runs your client and your server, and those are connected with effect.
I always go with a monorepo, with usually a
clientandserverapp, and a sharedapipackage 🤝
api defines shared Schema (as strict and refined as possible) and export an HttpApi.
apihas a single dependency:effect(beta) 💡
Both client and server share the same single source of truth, and effect derives all the http clients for you:
import { AuthMiddleware, ServerApi } from "@app/api"; // 👈 Shared API
import { Config, Context, Effect, Layer } from "effect";
import { FetchHttpClient, HttpClientRequest } from "effect/unstable/http";
import { HttpApiClient, HttpApiMiddleware } from "effect/unstable/httpapi";
class CurrentAccessToken extends Context.Service<CurrentAccessToken, string>()(
"CurrentAccessToken"
) {}
const AuthMiddlewareClient = HttpApiMiddleware.layerClient(
AuthMiddleware,
Effect.fn(function* ({ next, request }) {
const token = yield* CurrentAccessToken;
return yield* next(HttpClientRequest.bearerToken(request, token));
})
);
export class ApiClient extends Context.Service<ApiClient>()("ApiClient", {
make: Effect.gen(function* () {
const baseUrl = yield* Config.string("API_BASE_URL");
return {
withAccessToken: <A, E, R>(
f: (
api: HttpApiClient.ForApi<typeof ServerApi>
) => Effect.Effect<A, E, R>,
accessToken: string
): Effect.Effect<A, E, Exclude<R, CurrentAccessToken>> =>
Effect.gen(function* () {
const api = yield* HttpApiClient.make(ServerApi, { baseUrl });
return yield* f(api);
}).pipe(
Effect.provide(
Layer.mergeAll(AuthMiddlewareClient, FetchHttpClient.layer),
),
Effect.provideService(CurrentAccessToken, accessToken),
),
};
}),
}) {
static readonly layer = Layer.effect(this, this.make);
}Keep your api definition clean, and watch everything else in the app just work as a consequence, guided by types.
Backend: all you need is effect
server implements the HttpApi from api. And all it needs, again, it's mostly effect 💁🏼♂️
Effect has wrappers for all major databases, AI APIs, and more, no custom implementation needed 🙌
Example: I am using Cloudflare, D1 as database, and my app calls AI. I use @effect/sql-d1 and @effect/ai-openai-compat.
But you are not required to go effect packages only. For example, I use Clerk for authentication, I can just bring @clerk/backend and wrap it with effect to make it work:
import { createClerkClient } from "@clerk/backend";
import { Config, Context, Effect, Layer, Redacted, Schema } from "effect";
class ClerkError extends Schema.TaggedErrorClass<ClerkError>()("ClerkError", {
cause: Schema.Unknown,
}) {}
export class Clerk extends Context.Service<Clerk>()("Clerk", {
make: Effect.gen(function* () {
const { publishableKey, secretKey } = yield* Config.all({
publishableKey: Config.redacted("CLERK_PUBLISHABLE_KEY"),
secretKey: Config.redacted("CLERK_SECRET_KEY"),
});
const clerkClient = createClerkClient({
publishableKey: Redacted.value(publishableKey),
secretKey: Redacted.value(secretKey),
});
return {
authenticateRequest: (request: globalThis.Request) =>
Effect.tryPromise({
try: () => clerkClient.authenticateRequest(request),
catch: (error) => new ClerkError({ cause: error }),
}).pipe(
Effect.timeout("5 seconds"),
Effect.catchTag("TimeoutError", (cause) =>
new ClerkError({ cause }).asEffect()
)
),
};
}),
}) {
static readonly layer = Layer.effect(this, this.make);
}That's what it means to "Effectify" your codebase:
effectprovides most of it, but it also allows to bring your own 🤝
And now watch as major providers start bringing effect-native integrations (starting with Drizzle) 🤝
Drizzle now natively supports Effect v4
Effect also on the client, no matter what client
With effect v4 the effect-client story becomes even more appealing, with reduced bundle size and increased speed.
Effect on the client is the same as the backend, same logic, different runtime 💁🏼♂️
Same as server, also on the client I have a services folder with all the logic wrapped into effects. And the modules are abundant also on the client:
HttpClient(no needfetch)Reactivity(syncing between components, ineffect)IndexedDb(the right way)
A possible new addition with state machines is also on its way here 👀
Effect's Atom is there as well to solve most of your state management hurdles.
Result: all you need for business logic on the client is 1 dependency (
effect) 🪄
Effect end to end, monorepo, AI agents work great with it, all type checked. Add a few more guardrails with the LSP and some custom linting rules, and just watch everything "just work" ☑️
See you next 👋



