Skip to main content

What is a "domain"?

In Effector, a domain is a container that groups related parts of the logic together: store, event, effect, sample, and so on.

Put simply:

A domain is an "area of responsibility" (a feature module) that holds all the related state, events, and effects.


1. What a Domain is conceptually

Effector is a reactive system where you can create many events and stores. As a project grows, there can be hundreds of them, and you need to organize all of that.

This is where Domain helps: it creates hierarchy, encapsulation, and a single point of control for a module.


2. Example of the simplest Domain

javascript
import { createDomain } from 'effector' // create a domain const userDomain = createDomain('user') // create events, stores, and effects inside it const fetchUserFx = userDomain.createEffect(async (id: number) => { const res = await fetch(`/api/users/${id}`) return res.json() }) const userLoaded = userDomain.createEvent() const $user = userDomain.createStore(null) .on(fetchUserFx.doneData, (_, user) => user) .on(userLoaded, (_, user) => user)

Now everything related to the user lives in one domain:

  • effects,
  • events,
  • stores.

3. Why a Domain is needed

GoalDescription
Grouping logicEverything related to one feature can be kept in one area.
Lifecycle managementA domain can be reset, cleared, or cloned entirely.
Error handling and loggingA domain can intercept errors from all of its effects.
SSR and isolationYou can create separate domain instances per user request (avoiding state conflicts).

4. Error handling inside a Domain

A domain has built-in hooks, such as .onCreateEffect, .onCreateStore, .onCreateEvent. You can use them to centrally log or handle events.

javascript
userDomain.onCreateEffect(effect => { effect.fail.watch(({ error }) => { console.error('Effect error:', error) }) })

This way, if an error occurs in any effect inside userDomain, it gets intercepted automatically.


5. Domain hierarchy

Domains can be nested inside each other:

javascript
const appDomain = createDomain('app') const userDomain = appDomain.createDomain('user') const authDomain = appDomain.createDomain('auth')

This is useful for large applications:

  • appDomain - the root, global state;
  • userDomain - user data;
  • authDomain - authentication and tokens;
  • cartDomain - the cart (in e-commerce);
  • and so on.

6. Resetting and clearing a Domain (lifecycle)

Effector lets you recreate a Domain (for example, on logout):

javascript
import { fork, allSettled } from 'effector' const scope = fork({ values: { $user: null } }) await allSettled(fetchUserFx, { scope, params: 1 })

This gives you the ability to:

  • have separate state per client (SSR, multiple instances),
  • clear all state in a domain when the user logs out.

7. Domain as a "feature module"

You can think of it this way:

javascript
userDomain ├── events/ │ └── userLoaded ├── stores/ │ └── $user ├── effects/ │ └── fetchUserFx └── samples/ └── connect event → effect

This is essentially a mini-application inside the application. A domain describes "what" a specific part of the system does.


8. Difference from plain code without a Domain

Without a DomainWith a Domain
CreationcreateStore(), createEvent()domain.createStore(), domain.createEvent()
IsolationEverything is globalAll entities are grouped
LoggingMust be done manuallyCan be centralized
ErrorsMust be caught separatelyDomain intercepts them
SSRMust be cleared manuallyThe whole scope can be cloned

SUMMARY

A domain is a container (or module) in Effector that holds all related state, events, and effects. It helps:

  • structure the code,
  • manage the store's lifecycle,
  • centralize error handling,
  • isolate state between users and requests.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.