To ensure correctness at scale, FRAGMENT's consistency mode lets you build guardrails without sacrificing performance.
You can configure consistency within your Schema to make granular tradeoffs between throughput and consistency.
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:
entries: eventual for Ledgers that require high throughput but can tolerate a stale entry listentries: strong for Ledgers that have lower throughput but require strong consistency, such as those powering reconcilation dashboards{
"consistencyConfig": {
"entries": "strong"
},
"chartOfAccounts": [...]
}By default, all Ledgers use eventual consistency.
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.ownBalanceUpdates within a Ledger Account's definition:
ownBalanceUpdates: eventual for Ledger Accounts that require high throughput but can tolerate stale balances, such as those used for reportingownBalanceUpdates: strong for Ledger Accounts that have lower throughput but require strong consistency, such as those used to authorize transactionsSimilarly, to configure the consistency of an account's lines, set consistencyConfig.lines:
lines: eventual for Ledger Accounts that require high throughput but can tolerate a stale line listlines: strong for Ledger Accounts that have lower throughput but require strong consistency, such as those powering transaction histories displayed to end users{
"accounts": [
{
"key": "user-balance",
"template": true,
"type": "asset",
"consistencyConfig": {
"ownBalanceUpdates": "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:
{
"chartOfAccounts": {
"defaultConsistencyConfig": {
"ownBalanceUpdates": "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.
To query a strongly consistent ownBalance, set consistencyMode to strong when querying the Ledger Account:
query GetOwnBalances(
$ledgerAccount: LedgerAccountMatchInput!
) {
ledgerAccount(ledgerAccount: $ledgerAccount) {
ownBalance(consistencyMode: strong)
ownBalances(consistencyMode: strong) {
nodes {
amount
currency {
code
}
}
}
}
}By default, balance queries on all Ledger Accounts are eventually consistent.
Restrictions:
ownBalance supports strongly consistent reads; balance and childBalance support only eventually consistent readsat with consistencyMode to query strongly consistent historical balancesEntry 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.
{
"type": "pay-employee",
"lines": [...],
"conditions": [
{
"account": {
"path": "bank-account"
},
"precondition": {
"ownBalance": {
"eq": "{{current_balance}}"
}
}
}
]
}Use postcondition to guarantee that a write never puts a Ledger Account's balance in an undesirable state.
{
"type": "pay-employee",
"lines": [...],
"conditions": [
{
"account": {
"path": "bank-account"
},
"postcondition": {
"ownBalance": {
"gte": "0"
}
}
}
]
}Restrictions:
ownBalance, which changes only for Ledger Accounts directly posted to in the Ledger Entry.consistencyConfig.ownBalanceUpdates set to strongYou 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.
{
"accounts": [
{
"key": "user-balance",
"template": true,
"type": "asset",
"consistencyConfig": {
"groups": [
{
"key": "invoice_id",
"ownBalanceUpdates": "strong"
}
]
}
}
]
}See Group Ledger Entries for more information about how to use Ledger Entry Groups.
To query a strongly consistent Ledger Entry Group balance, set consistencyMode to strong or use_account when querying the group's balances.
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: