---
title: "Concurrency and resources"
description: "The shared `and` model, transport-specific cancellation, and resource ownership in core and Effect code."
image: "https://hem.run/social/hem.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://hem.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Concurrency and resources

Hem uses a single binding-group syntax for independent work. Group members joined with `and` are evaluated independently; no member can reference a name bound by another member in the same group. The marker on each member specifies the transport.

## `and` groups

### Pure groups

A plain `let` group evaluates initializers from left to right, then binds the names. All values are computed before the bindings become available, matching the structure of carrier groups without introducing asynchronous execution.

```hem
let first = readFirst()
and second = readSecond()
let total = first + second
```

The emitted TypeScript consists of standard sequential bindings. A group does not allow referencing an earlier member; split dependent operations into separate sequential bindings.

### Awaited groups

When every member is marked with `await`, Hem runs all promise expressions concurrently using `Promise.all` and binds the results in declaration order. Destructured members use a tuple result; identifier members use positional mapping.

```hem
let user = await fetchUser(id)
and settings = await fetchSettings(id)
show(user, settings)
```

If a promise rejects, the entire group rejects. Because JavaScript promises do not provide a general cancellation mechanism, other in-flight operations continue running unless the underlying APIs implement cancellation. Use an explicit cancellable API when an operation must observe an `AbortSignal`.

### Effect groups

Inside an `effect { }` block, every member is bound using postfix `!`. Hem compiles the group to `Effect.all` with unbounded concurrency. If any member fails, in-flight sibling fibers are interrupted immediately so failing operations do not continue running in the background.

```hem
let dashboard = (id: string) => effect {
  let user = fetchUser(id)!
  and preferences = fetchPreferences(id)!
  render(user, preferences)
}
```

Effect cancellation is structured: interruption propagates to active child fibers in the group. This distinguishes Effect groups from awaited `Promise` groups; Hem syntax remains identical except for the marker and enclosing block type.

### Carrier groups

Canonical `Option` and `Result` bindings follow the same grouping rules. All member expressions evaluate first. After evaluation, Hem inspects members in declaration order; the first `None` or `Err` residual propagates unchanged to the nearest arrow, async arrow, or Effect success-channel boundary. Success values are bound normally.

```hem
let load = (id: string): Result<{ user: User, theme: string }, LoadError> => {
  let Ok(user) = loadUser(id)
  and Ok(settings) = loadSettings(id)
  Result.ok({ user: user, theme: settings.theme })
}
```

An awaited carrier group requires `await` on every member and runs via `Promise.all` before checking residuals. Carrier groups do not introduce cancellation; behavior depends on whether the underlying transport is a Promise or an Effect.

### Scope-safe acquisition groups

With the Effect extension enabled, `use` bindings can form a group with `and`. Acquisitions run concurrently and register finalizers in the enclosing scope. If one acquisition fails, the scope releases previously acquired resources, ensuring safe concurrent acquisition.

Core `use` groups are rejected. Core disposal relies on JavaScript's lexical `using` scope, which cannot handle interruption or clean up partially completed concurrent acquisitions.

```hem
let report = (sql: string) => effect {
  use db = Db.acquire
  and cache = Cache.acquire
  let rows = db.query(sql)!
  renderRows(rows, cache)
}
```

Markers within a group must be uniform: all pure, all awaited, all Effect-bound with `!`, or all extension `use` bindings. Mixing `let` and `use` is prohibited, and nested `!` inside a member is rejected because it would serialize execution.

## Dependent work

Hem rejects sibling references within the same group. Move dependent computations to a subsequent sequential binding, or extract the dependent logic into a sub-flow and treat that sub-flow as one member of the group.

```hem
let load = (id: string) => effect {
  let user = fetchUser(id)!
  and orgs = fetchOrgs(user.orgId)!
  { user, orgs }
}
```

Diagnostic HEM2007 indicates a sibling binding reference. To handle dependent Effect graphs, use separate `let` bindings, destructure a named sub-flow, use `Effect.fork` and `Fiber.join`, or use `Effect.forEach` with explicit concurrency settings. Plain async code uses an async helper or platform promise and cancellation APIs.

## Resource ownership

### Core `use`

`use pat = expression` requires a value implementing `Disposable` or `AsyncDisposable`. In core Hem, this compiles to JavaScript's `using` or `await using` based on the resource type. Resources are released in last-in-first-out (LIFO) order when the enclosing block exits, including on thrown errors. Core disposal has no interruption model and relies on the host runtime's disposal protocol.

```hem
let readReport = async () => {
  use file = await openReport()
  await file.read()
}
```

Limit the scope of `use` to the resource's active lifetime. Binding a non-disposable value produces type error HEM2012; use an adapter if a library does not implement the standard disposal protocol.

### Effect `use`

Inside an `effect { }` block, `use` binds an Effect requiring a `Scope`. The enclosing effect block serves as the scope: Hem wraps blocks containing scoped acquisitions in `Effect.scoped`. Registered finalizers run in LIFO order on success, typed failure, defect, or interruption. The scope wrapper sits inside any postfix `catch`, ensuring cleanup finishes before error recovery executes.

```hem
let report = (sql: string) => effect {
  use db = Db.acquire
  let rows = db.query(sql)!
  renderRows(rows)
}
```

Binding a Scope-requiring Effect with `!` is rejected (HEM4105); `use` is required to transfer ownership explicitly.

### `resource { }`

`resource { }` follows the same acquisition and cleanup semantics as `effect { }`, but leaves the scope open. `Scope` remains in the returned Effect's requirement channel, and any `use` or `defer` statements register into the caller's scope. Use `resource { }` when creating services or layers whose lifetime is managed by the caller.

```hem
let DatabaseLive = Layer.effect(Database, resource {
  use db = Db.acquire
  asDatabase(db)
})
```

The block type determines ownership: `effect { }` closes its scope, while `resource { }` passes the scope to the caller.

### `defer`

`defer cleanup` registers an infallible `Effect<void, never, R>` without binding a value. Wrap synchronous cleanup functions with `Effect.sync`, explicitly discard return values, and handle typed errors before registration.

```hem
let serve = effect {
  defer Effect.sync(() => instruction.clear(id))
  work()!
}
```

`defer` does not accept an exit value. For exit-aware cleanup, call `Effect.addFinalizer` directly. Both `use` and `defer` execute in reverse registration order on any Effect exit, including interruption.

## Related diagnostics

| Code | Meaning |
| --- | --- |
| HEM2007 | A group member references a sibling binding. |
| HEM2008 | Group markers or binder kinds are mixed, or core `use` appears in a group. |
| HEM2009 | A group member contains a nested bind that would serialize work. |
| HEM2012 | `use` needs a disposable resource in core. |
| HEM4105 | A Scope-carrying Effect was bound with `!` instead of `use`. |
| HEM4112 | `defer` appears outside an Effect scope. |
| HEM4113 | A deferred cleanup does not satisfy the cleanup contract. |

## Normative source

Specification 0.2, §4 (bindings), §9 (errors and exceptions), and §14.6–§14.7 (Effect
resources and concurrency). The tour's worked forms are in sections 20 and 21.

Source: https://hem.run/reference/concurrency-and-resources/index.mdx
