Skip to main content
Use .effect(...) when a procedure implementation should run as an Effect. Handlers can be generator callbacks, Effect.fn(...) callbacks, or functions that return an Effect.
effect-procedure.ts
const getUser = effectProcedure
  .input(z.object({ id: z.string() }))
  .effect(function* ({ input }) {
    const usersRepo = yield* UsersRepo;
    const user = yield* usersRepo.findById(input.id);
    return user;
  });
The handler receives the normal oRPC handler options, including input, context, errors, path, signal, and metadata.

Handler shape

handler-options.ts
const procedure = effectProcedure.effect(function* ({
  input,
  context,
  errors,
  path,
  signal,
}) {
  yield* Effect.logDebug("handling procedure", { path });

  if (signal?.aborted) {
    yield* Effect.logDebug("request was already aborted");
  }

  return { input, context, path, errorKeys: Object.keys(errors) };
});

Effect-returning handlers

Use a plain Effect-returning callback when you already have an Effect value, or when you want to keep a named Effect.fn(...) span inside the automatic procedure span.
effect-returning.ts
const getUser = effectProcedure.effect(
  Effect.fn("users.get")(function* ({ input }) {
    const usersRepo = yield* UsersRepo;
    return yield* usersRepo.findById(input.id);
  }),
);

const listUsers = effectProcedure.effect(() =>
  Effect.gen(function* () {
    const usersRepo = yield* UsersRepo;
    return yield* usersRepo.list();
  }),
);

Mix with standard oRPC handlers

You can put standard oRPC procedures and Effect procedures in the same router.
mixed-router.ts
import { os } from "@orpc/server";

export const router = {
  health: os.handler(() => "ok"),

  users: {
    get: effectProcedure.effect(function* ({ input }) {
      const usersRepo = yield* UsersRepo;
      return yield* usersRepo.findById(input.id);
    }),
  },
};
Use .handler(...) for plain synchronous or async procedures. Use .effect(...) when the handler needs Effect services, typed Effect failures, tracing, or Effect context.

Next steps

Last modified on June 15, 2026