tech

A few Effect modules and how I use them

Effect is everywhere in my codebases, full stack, back and front and scripts and whatever. A few core module are always there, and carry most of the logic. Here they are, and how I use them.


Sandro Maglione

Sandro Maglione

Software

2026 is the year of effect (once more), guaranteed 🤝

Even more than last year 👇

I am refining more and more patterns as I work more and more with effect

Here is a list of modules I am using (and why) with examples 👇


Config

Long gone are the days where I had to bother about .env variables and process 👋

The Config module abstracts all away in a single yield* Config. call:

export class Clerk extends Effect.Service<Clerk>()("Clerk", {
  effect: Effect.gen(function* () {
    const { secretKey, publishableKey } = yield* Config.all({
      secretKey: Config.redacted("CLERK_SECRET_KEY"),
      publishableKey: Config.redacted("CLERK_PUBLISHABLE_KEY"),
    });

    const clerkClient = createClerkClient({
      secretKey: Redacted.value(secretKey),
      publishableKey: Redacted.value(publishableKey),
    });

    return {
      // ...
    };
  }),
}) {}

Furthermore, with Schema even Config can be anything, with proper validation.

Notice how for example .redacted helps prevent leaking secret keys 🪄

By default nothing else is necessary, effect picks up process.env by default.

Otherwise, you can use PlatformConfigProvider to read .env (no dotenv necessary):

import { PlatformConfigProvider } from "@effect/platform";
import { NodeFileSystem } from "@effect/platform-node";
import { Effect, Layer } from "effect";

export const ConfigEnvProviderLayer = Layer.unwrapEffect(
  PlatformConfigProvider.fromDotEnv(".env").pipe(
    Effect.map(Layer.setConfigProvider),
    Effect.provide(NodeFileSystem.layer)
  )
);

Array

The Array module gives your arrays superpowers (and immutability) ⚡️

A few that I use all the times:

  • sortBy: sorting doesn't have to be complex, you can just use Order
  • append: don't bother with [...data, newData]
  • modify: safe updates
  • Array.NonEmptyReadonlyArray: makes array[0] always found
Array.sortBy(array, Order.mapInput(Order.Date, ({ createdAt }) => createdAt))
Array.append(array, newValue)
Array.modify(attempts, currentIndex, (attempt) => ({ ...attempt, userAttempt: value }))

You can just pipe a bunch of those to build any complex filtering/validation system.

Match

You won't find switch anymore in my codebases. It's all type-safe Match everywhere.

Match makes code future-proof: adding a new value causes compile errors to pop up here and there, instead of runtime back and forth ☑️

Match.withReturnType to type the response at the start, Match.exhaustive to close the pipe at the end:

export default function AssignmentIcon({
  assignment,
}: {
  assignment: typeof SkillAssignmentLabel.Type;
}) {
  return Match.value(assignment).pipe(
    Match.withReturnType<React.ReactNode>(),
    Match.when("not_applicable", () => <></>),
    Match.when("critical", () =>  <CircleOff />),
    Match.when("incorrect", () => <Ban />),
    Match.when("slip", () => <Minus />),
    Match.when("passable", () => <Check />),
    Match.when("natural", () => <CheckCheck />),
    Match.when("perfect", () => <Trophy />),
    Match.exhaustive
  );
}

Effect toolkit: Schema, Layer, ManagedRuntime and more

Of course, the core of effect is always there, no matter the codebase (frontend/backend or anything):

  • Effect: Effect.gen/Effect.fn everywhere
  • Schema: must-have for, well, anything and everything
  • Layer: composition solved for you

These 3 alone will carry you a long way forward (error handling, dependency injection, schema validation).

A few others: Function, Predicate, Queue, Stream

A few more ideas for you to explore:

  • Function: a few helper functions you don't need to write (e.g. Function.identity)
  • Predicate: a few helper checks you won't miss (e.g. Predicate.isNotNullable)
  • Stream: AI talks the language of streams, and effect has you covered
  • Queue: I recently used it to integrate a callback API with xstate

Even the above are not found always. In reality, even for a few of my (relatively) big projects with effect, the basics will cover a huge percent of your code.

But when you will go beyond, effect has you covered as well.

Recent example: I used the Ndjson module from @effect/platform to parse AI responses ✨


I am about to launch a few effect/xstate production apps, and with them I foresee a bunch more tips for patterns I learn while working with those tools.

2026 is gonna be insane.

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