[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Task](https://evolu.dev/docs/api-reference/common/Task) › acquireUseRelease

```ts
function acquireUseRelease<
  Resource,
  T,
  EAcquire,
  EUse,
  DAcquire,
  DUse,
  DRelease,
>(
  acquire: Task<Resource, EAcquire, DAcquire>,
  use: (resource: Resource) => Task<T, EUse, DUse>,
  release: (resource: Resource) => Task<void, never, DRelease>,
): Task<T, EAcquire | EUse, DAcquire & DUse & DRelease>;
```

Defined in: [packages/common/src/Task.ts:5287](https://github.com/evoluhq/evolu/blob/037c390af081e9944d616ff298a729515c5c5ab7/packages/common/src/Task.ts#L5287)

Runs acquire, use, and release as one bracketed [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task).

Acquire and release are masked once the helper starts, while use runs with
the previous abort mask restored. If acquire returns an error, release is not
run. Release must not return recoverable errors; handle expected cleanup
failures inside the release Task.

Use this when a resource, lease, lock, or session must always be released
after it is acquired, even when use fails or is aborted.

Prefer native `using`, `await using`, or [AsyncDisposableStack](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack) for
owned values that implement [Disposable](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management) or [AsyncDisposable](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html#using-declarations-and-explicit-resource-management). Use
`acquireUseRelease` when acquisition must be balanced with a separate release
step, such as unlocking, returning a pooled value, releasing a lease, or
logging out of a session.

### Example

```ts
import {
  assertErr,
  assertTrue,
  acquireUseRelease,
  createRun,
  err,
  ok,
  type Task,
  type Typed,
} from "@evolu/common";

interface Connection {
  readonly user: string;
  readonly isAvailable: boolean;
}

const openConnection: Task<Connection> = () =>
  ok({ user: "Ada", isAvailable: false });
const loadUser =
  (connection: Connection): Task<string, UserUnavailableError> =>
  () =>
    connection.isAvailable
      ? ok(connection.user)
      : err({ type: "UserUnavailable" });

interface UserUnavailableError extends Typed<"UserUnavailable"> {}

let connectionClosed = false;
const closeConnection =
  (_connection: Connection): Task<void> =>
  () => {
    connectionClosed = true;
    return ok();
  };

const queryUser = acquireUseRelease(openConnection, loadUser, (connection) =>
  closeConnection(connection),
);

await using run = createRun();
assertErr(await run(queryUser), { type: "UserUnavailable" });
// Release still runs when use returns a domain error.
assertTrue(connectionClosed);
```