# Configure Consistency
Source: https://fragment.dev/guides/configure-consistency
[Documentation index](https://fragment.dev/llms.txt)
To ensure correctness at scale, Fragment's consistency mode lets you build guardrails without sacrificing performance.
[Visual: configureConsistency. View on the HTML page.](https://fragment.dev/guides/configure-consistency)
You can configure consistency within your Schema to make granular tradeoffs between throughput and consistency.
## Ledger Configuration
You can configure the consistency of the Ledger Entries list query in your Ledger. To do this, set `consistencyConfig` at the top level of your Schema:
- Use `entries: eventual` for Ledgers that require high throughput but can tolerate a stale entry list
- Use `entries: strong` for Ledgers that have lower throughput but require strong consistency, such as those powering reconcilation dashboards
```json title="Configuring consistency"
{
"consistencyConfig": {
"entries": "strong"
},
"chartOfAccounts": [...]
}
```
By default, all Ledgers use `eventual` consistency.
## Ledger Account Configuration
You can configure the consistency of balances, as well as the Ledger Lines list query, in your Ledger Account.
To configure an account's balance consistency, set `consistencyConfig.totalBalanceUpdates` within a Ledger Account's definition. `totalBalanceUpdates` controls the consistency with which the `selfTotal`, `childTotal` and total `balance` components of the account are updated. When `totalBalanceUpdates` is set to `strong`, any entry posted to the account or any of its children will update the account's balance immediately.
Options:
- Use `totalBalanceUpdates: eventual` for Ledger Accounts that require high throughput but can tolerate stale balances, such as those used for reporting
- Use `totalBalanceUpdates: strong` for Ledger Accounts that have lower throughput but require strong consistency, such as those used to authorize transactions
Similarly, to configure the consistency of an account's lines, set `consistencyConfig.lines`:
- Use `lines: eventual` for Ledger Accounts that require high throughput but can tolerate a stale line list
- Use `lines: strong` for Ledger Accounts that have lower throughput but require strong consistency, such as those powering transaction histories displayed to end users
```json title="Configuring consistency"
{
"accounts": [
{
"key": "user-balance",
"template": true,
"type": "asset",
"consistencyConfig": {
"totalBalanceUpdates": "strong",
"lines": "eventual"
}
}
]
}
```
By default, all Ledger Accounts use `eventual` for both properties.
For low-throughput applications, setting all Ledger Accounts as `strong` may make implementation easier. To do this, set `defaultConsistencyConfig` on `chartOfAccounts`:
```json title="Configuring default consistency"
{
"chartOfAccounts": {
"defaultConsistencyConfig": {
"totalBalanceUpdates": "strong",
"lines": "strong"
},
"accounts": [...]
}
}
```
Strongly consistent Ledger Accounts generally won't have children, but in all cases child Ledger Accounts inherit the parent's `consistencyConfig` setting.
## Balance queries
To query a strongly consistent `balance`, set `consistencyMode` to `strong` when querying the Ledger Account:
```graphql title="Setting consistency on balance reads"
query GetBalances(
$ledgerAccount: LedgerAccountMatchInput!
) {
ledgerAccount(ledgerAccount: $ledgerAccount) {
balance(consistencyMode: strong)
balances(consistencyMode: strong) {
nodes {
amount
currency {
code
}
}
}
}
}
```
By default, balance queries on all Ledger Accounts are eventually consistent.
Restrictions:
- Querying a strongly consistent balance on an eventually consistent Ledger Account throws a GraphQL error
- You cannot combine `at` with `consistencyMode` to query strongly consistent historical balances
## Entry conditions
Entry conditions are rules defined in your Schema to manage concurrency and enforce correctness within your Ledger.
Conditions are evaluated when a Ledger Entry is posted. If a condition is not met, the Ledger Entry is not posted and the mutation returns a `BadRequestError` with code `conditional_request_failed`.
Use `precondition` when your application reads a balance and needs to guarantee that it hasn't changed before posting the Ledger Entry.
```json title="Using precondition"
{
"type": "pay-employee",
"lines": [...],
"conditions": [
{
"account": {
"path": "bank-account"
},
"precondition": {
"totalBalance": {
"eq": "{{current_balance}}"
}
}
}
]
}
```
Use `postcondition` to guarantee that a write never puts a Ledger Account's balance in an undesirable state.
```json title="Using postcondition"
{
"type": "pay-employee",
"lines": [...],
"conditions": [
{
"account": {
"path": "bank-account"
},
"postcondition": {
"totalBalance": {
"gte": "0"
}
}
}
]
}
```
Restrictions:
- Entry conditions using `totalBalance` apply to the account's total balance, which includes both the account's own lines and its children's lines.
- Ledger Accounts referenced in Entry conditions must have `consistencyConfig.totalBalanceUpdates` set to `strong`
- Linked Ledger Accounts do not support Entry conditions
## Repeated conditions
When using [repeated](https://fragment.dev/markdown/guides/post-ledger-entries.md#repeated-lines) Lines, conditions can be repeated using the same `repeated` key. This lets you enforce a condition on a variable set of accounts:
```json title="Ledger Entry with repeated lines and conditions"
{
"type": "batch_transfer",
"lines": [
{
"key": "from",
"account": { "path": "liabilities/users:{{from_user}}/available" },
"amount": "-{{amount}}",
"repeated": { "key": "transfers" }
},
{
"key": "to",
"account": { "path": "liabilities/users:{{to_user}}/available" },
"amount": "{{amount}}",
"repeated": { "key": "transfers" }
}
],
"conditions": [
{
"account": { "path": "liabilities/users:{{from_user}}/available" },
"postcondition": { "totalBalance": { "gte": "0" } },
"currency": { "code": "USD" },
"repeated": { "key": "transfers" }
}
]
}
```
Each element in the `transfers` array generates both the transfer lines and its own balance condition.
## Consistent Groups
You can configure an account to have a strongly-consistent ownBalance for specific group keys.
To do this, use the `consistencyConfig.groups` configuration in the Schema.
```json title="Ledger Entry Group balance consistency"
{
"accounts": [
{
"key": "user-balance",
"template": true,
"type": "asset",
"consistencyConfig": {
"groups": [
{
"key": "invoice_id",
"ownBalanceUpdates": "strong"
}
]
}
}
]
}
```
See [Group Ledger Entries](https://fragment.dev/markdown/guides/group-ledger-entries.md) for more information about how to use Ledger Entry Groups.
## Query Consistent Groups
To query a strongly consistent Ledger Entry Group balance, set `consistencyMode` to `strong` or `use_account` when querying the group's balances.
```graphql title="Setting consistency on group ownBalance reads"
query ListLedgerEntryGroupBalances(
$ledger: LedgerMatchInput!
$groupKey: SafeString!
$groupValue: SafeString!
$consistencyMode: ReadBalanceConsistencyMode
) {
ledgerEntryGroup(ledgerEntryGroup: {
ledger: $ledger,
key: $groupKey,
value: $groupValue,
}) {
balances {
nodes {
account {
path
}
ownBalance(consistencyMode: $consistencyMode)
}
}
}
}
```
By default, Ledger Entry Group balances are eventually consistent. Like other consistency options, enabling strong consistency will reduce the maximum throughput of an account.
Restrictions:
- Ledger Entry Group balances cannot be used for Entry conditions.
- Querying a strongly consistent Ledger Entry Group balance without configuring strong group consistency for that Ledger Account throws a GraphQL error.
## Legacy ownBalance Consistency
`ownBalanceUpdates` is the legacy way of setting account level consistency. It only controls the consistency of the account's own balance (excluding children). `childTotal` and `balance` default to `eventual` on Schemas using `ownBalanceUpdates`. A Ledger Account cannot have both `totalBalanceUpdates` and `ownBalanceUpdates` set.
Schemas using `ownBalanceUpdates` can only use `ownBalance` conditions. These conditions only apply to the account's own balance and require `consistencyConfig.ownBalanceUpdates` set to `strong`.
Any examples or documentation on this page that use `totalBalanceUpdates` or `totalBalance` conditions can be adapted for a legacy `ownBalanceUpdates` Schema by replacing:
- `totalBalanceUpdates` with `ownBalanceUpdates` in your consistency config
- `totalBalance` with `ownBalance` in your entry conditions