β€’

tech

My Effect v4 beta migrations

Effect v4 beta is out. It's time to start migrating everything to it right away, of course. I already started. Here is how it went, what you should know, and what are the improvements.


Sandro Maglione

Sandro Maglione

Software

Effect v4 beta is out πŸš€

And with it my journey into full migration of my effect codebases πŸ‘€

Let's go πŸš€ Expect more content from me all about v4, as I migrate all my projects and discover new patterns And also, the course on Typeonce updated to v4 πŸ”œ

Effect | TypeScript at Scale
Effect | TypeScript at Scale
@EffectTS_

Effect v4 is in beta. πŸš€ Rewritten runtime. Smaller bundles. Unified package system. The most ambitious release we've made so far. Here's what's new. 🧡

Introducing Effect v4 beta. `bun add effect@4.0.0-beta.0`
40
Reply

I completed a few already. Here is what happened, what changed, what's new πŸ‘‡


Migrations in the AI era

Migrations used to be a massive effort of "codemod" and weeks of time.

You guess? Not anymore with AI πŸ’πŸΌβ€β™‚οΈ

Effect v4 brings many renamed APIs and new patterns. Most are already documented in the effect-smol repository.

Here is what I did:

  • Inside a local .agents folder, clone both effect (v3) and effect-smol (v4)
  • Point at both inside AGENTS.md
  • Tell AI to design a migration plan by comparing v3 to v4 from source and migration docs

(Not) Surprisingly, this was mostly enough to one shot "smaller" codebases.

Most of my code is full stack effect, so both server (HttpApi) and client πŸ—οΈ

A migration is still a migration

Of course, don't trust AI to just get it all right.

For larger codebases, the process got more complex πŸ€”

You know something will break when the AI declares: "This looks like a massive amount of work..." 🫠

And in fact, more than once the AI got into tangents confusing repositories and APIs. Well, make sure to guide the AI in the migration if it's "massive" πŸ’πŸΌβ€β™‚οΈ

Major API changes

Here is a practical list of the most common code changes from v3 to v4.

First, package installs. No more confusion with effect and @effect/* versions. Now all effect libraries run the same version (e.g. effect-beta.10).

Furthermore, no more @effect/platform and similar. It's now all into effect under effect/unstable:

import { Effect, flow, Layer, ServiceMap } from "effect";
import {
  FetchHttpClient,
  HttpClient,
  HttpClientRequest,
  HttpClientResponse,
} from "effect/unstable/http";
import { HttpApiClient } from "effect/unstable/httpapi";

Only platform-specific packages need a separate installation:

"dependencies": {
  "@effect/sql-d1": "4.0.0-beta.5",
  "effect": "4.0.0-beta.5"
}

Second major change: effect services. No more confusion with multiple options and Default layers. Now it's all under ServiceMap.Service, and "back" to the "new" make pattern:

export class ApiClient extends ServiceMap.Service<ApiClient>()("ApiClient", {
  make: Effect.gen(function* () {
    const baseUrl = yield* ApiBaseUrlConfig;
    return yield* HttpApiClient.make(ServerApi, { baseUrl });
  }),
}) {
  static readonly layer = Layer.effect(this, this.make);
}

Third massive change: schema (all of it). This will be the biggest hurdle. A few examples from my code:

  • Schema.Number.pipe(Schema.int(), Schema.positive()) to Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0))
  • Schema.nonNegative() to Schema.isGreaterThanOrEqualTo(0)
  • Schema.pattern(regex) to Schema.isPattern(regex)

Beside this, there is a lot more! 🫠

Common APIs renamed (e.g. Option.fromNullable(value) to Option.fromNullishOr(value)), HttpApi changes, layers creation and much more.

What you get in return

There are many practical improvements in v4 (bundle size, performance, removed redundancy).

It's early to say, but here are my previous and after deployments "official and absolutely valid in all cases" subjective benchmarks (bundle size):

Before
Total Upload: 9752.27 KiB / gzip: 900.19 KiB
Worker Startup Time: 589 ms
Client index.js: 965.15 kB β”‚ gzip: 302.66 kB
After
Total Upload: 9023.81 KiB / gzip: 779.09 KiB
Worker Startup Time: 471 ms
Client index.js: 810.88 kB β”‚ gzip: 254.95 kB

Indeed, smaller and faster at first glance 🫑


Many more beta releases are coming as the community completes migrations and reports issues (me included) πŸ‘€

Let me repeat, once again: now it's time for you (anyone) to jump into effect

See you next πŸ‘‹

Start here.

Every week I dive headfirst into a topic, uncovering every hidden nook and shadow, to deliver you the most interesting insights

Not convinced? Well, let me tell you more about it