---
title: Effect version policy
description: Which Effect versions effract supports, how beta churn is tracked, and the commitment at effract v1 — alignment with Effect v4 stable.
group: Advanced
order: 4
---

Effect v4 is still in beta, and the beta line has seen real API churn (the `Context` → `ServiceMap` →
`Context` rename-and-revert being the notable one). effract sits directly on that surface, so this page
states plainly what you can rely on today and what changes at v1.

## Supported versions

effract's peer range is:

```json
"peerDependencies": {
  "effect": ">=4.0.0-beta.88 <5.0.0",
  "react": "^19.0.0"
}
```

- **Effect** — `>=4.0.0-beta.88` up to (but not including) `5.0.0`. effract tracks the v4 beta line and
  pins the exact beta it is tested against via the workspace **catalog**; the peer range stays wide so a
  slightly newer beta still satisfies it and no second copy of Effect is installed.
- **React** — `^19.0.0`. effract uses `use`, `useSyncExternalStore`, and Suspense semantics that are
  stable as of React 19.

## How beta churn is tracked

- The repo pins one exact Effect beta in its catalog and runs the full `just verify` gate against it. When
  a new beta lands, the pin is bumped in one place, the gate is re-run, and any break is fixed before the
  next effract release.
- Breaking changes in the Effect beta that reach effract's public surface are called out in
  [`CHANGELOG.md`](https://github.com/get-tmonier/effract/blob/main/CHANGELOG.md). Because the peer range
  is a range (not an exact pin), most beta bumps in your app need no effract release.
- effract's own runtime `dependencies` are **empty** — Effect and React are peers, imported and resolved
  to your app's single copy. You are never carrying an effract-bundled Effect.

## The commitment at effract v1

effract **v1.0 lands aligned with Effect v4 stable.** At that point:

- The peer range's lower bound moves to the v4 stable release, and the pre-release beta constraint is
  dropped.
- The public API is frozen under semver: within `1.x`, no breaking changes to the exported surface;
  breaking changes wait for `2.0`.
- Migration notes from the `0.x` line to `1.0` ship in the changelog.

Until then, treat the `0.x` line as tracking the Effect v4 beta: minor versions may adjust to upstream
churn, and the changelog is the source of truth for what moved.

## Deprecation & API-freeze policy (from v1.0)

- **Semver, strictly.** Within `1.x`: additions are minors, fixes are patches, and **no breaking change**
  to the exported surface ships without a major. The public surface is the two package entries
  (`@tmonier/effract` client + `react-server`) and `@tmonier/effract-vite` / `@tmonier/effract-test` /
  `@tmonier/create-effract`.
- **Deprecate before removing.** A symbol slated for removal is marked `@deprecated` (with the
  replacement) for at least one minor before it is removed in the next major. Deprecations are listed in
  the changelog.
- **Documented API == exported API.** CI enforces it: the `react-server` entry's surface is asserted by a
  test (hooks must not leak to the server build), and `knip` fails the gate on an exported symbol nothing
  uses. So the docs and the exports cannot silently diverge.
- **Effect coupling.** effract re-exports nothing from Effect; you depend on your own `effect`. A breaking
  change in Effect that reaches effract's surface is called out in the changelog and, if it forces a break,
  waits for effract's next major.
