---
title: "Account Retirement"
description: "Account retirement forgets one account's zero, unused runtime state. An unknown or already retired account succeeds without a change."
---

# Account Retirement

Account retirement forgets one account's zero, unused runtime state.
An unknown or already retired account succeeds without a change.

## What Retirement Changes

On success, policies remove their account-scoped state. The engine clears the
account's explicit currency, group membership, and own block of any origin.
Rate-limit window logs and zero realized P&L entries are among the policy
state removed. Per-account policy configuration is not removed: a policy
refuses retirement while its configuration names the account. Group currency,
group-level and engine-wide blocks remain, and the separate market-data
service is not touched.

## Refusal and Atomicity

A policy refuses retirement for `configuration references account`,
`non zero state`, `operation in progress`, or `evaluation failed`. A failed
evaluation includes a failed custom-policy callback. The error identifies
every refusing policy in registration order. A refusal removes nothing. A
failing rollback finalizer can still arm the engine
[kill switch](Account-Blocking.md#mutation-finalizer-contract):
a built-in policy blocks the account; a custom policy blocks every account
until `unblock all`.

For Spot Funds, flatten positions to clear their cost basis. Use `apply account
adjustment` to zero holdings and position P&L, and `set spot funds account pnl`
to zero account P&L. For the P&L bounds kill switch, use `set account pnl` to
zero each realized-P&L entry. See [Account Adjustments](Account-Adjustments.md),
[Spot Funds runtime reconfiguration](Spot-Funds.md#runtime-reconfiguration), and
the [force-set section](Dynamic-Policy-Reconfiguration.md#force-set-accumulated-pl)
for the per-language forms. Remove account-specific policy settings that still
reference the ID, then finish or discard in-flight operations before retrying.

The engine pauses account-state writers during the check and removal. It
commits policy removals only if every policy accepts. If a commit finalizer
fails, some policy state may already be removed, the
[kill switch](Account-Blocking.md#mutation-finalizer-contract) is armed, and the
account's currency, membership, and own block remain. A built-in policy's
failure blocks the account; a custom policy's blocks every account until
`unblock all`.

## Caller Contract

**Before retirement, finalize or drop every pre-trade request, reservation,
and drop-copy operation for the account. Do not run operations,
configuration, or account administration for it concurrently with retirement.**
An unexecuted request can hold no policy state and be invisible to the engine.
Executing it after retirement treats the account as new; after ID reuse, it
can act on someone else's account.

Reuse the account ID only after retirement succeeds and all old handles are
gone. **After `finalizer failed`, never reuse that ID, even if a later
retirement succeeds.**

## Custom Policies

A custom policy that keeps account-scoped state must implement the retirement
hook. The default means the policy holds no such state; otherwise state can
survive retirement and be inherited by a reused ID. The hook checks for zero,
unused state and registers removals for commit. It must not remove state
directly. A refusal rolls back the collected mutations without removal. Hooks
and their mutations run under the engine's exclusive account-state transition;
they must not call state-changing engine operations.

- Go: implement the optional `pretrade.AccountRetirementPolicy` interface.
  Its `RetireAccount` hook registers removals through `tx.Mutations`.
- Python, JavaScript, and C++: custom policies retain the default declaration
  that they hold no account-scoped state.
- Rust: implement `PreTradePolicy::retire_account` and register removals in
  `Mutations`.
- C: provide `OpenPitPretradePreTradePolicyRetireAccountFn` and register
  commit and rollback callbacks through `openpit_mutations_push`. A null
  callback declares no account-scoped state.

## Availability

- Go: `Engine.RetireAccount`, `ClientEngine.RetireAccount`,
  `AsyncEngine.RetireAccount`, and the `ChainBuilder.RetireAccount` step.
- Python, JavaScript, and C++: no account-retirement API.
- Rust: `Engine::retire_account`.
- C: `openpit_engine_retire_account`.

## Related Pages

- [Account Groups](Account-Groups.md): membership removed by retirement
- [Account Blocking](Account-Blocking.md): account, group, and engine-wide blocks
- [Policy API](Policy-API.md): custom policy hooks and mutations
- [Async Engine](Async-Engine.md): Go account-lane retirement and chain step
- [Errors](Errors.md): retirement error types per language
- [Spot Funds](Spot-Funds.md): holdings and P&L state
