GitHub

API changes

0.17.0

Applications using the TigerBeetle Client 0.16.x will require changes when upgrading to 0.17.x.

Future releases of the TigerBeetle cluster tagged as 0.17.x will continue to support old clients for an extended period, giving application developers time to plan a smooth upgrade to the new client library while independently upgrading the cluster to newer releases.

New return type for create_accounts and create_transfers.

The TigerBeetle release 0.17.0 introduced a new API for handling results when creating Accounts and Transfers.

The previous API for create_accounts and create_transfers reported outcomes only for failed events, returning a sparse array of results. Each result included the index of the failed element within the event batch and the corresponding error code. Successfully created events were not returned by the TigerBeetle cluster, and the application could safely assume them as ok.

While this approach prioritized saving network bandwidth by omitting results for the common happy path, it didn’t provide enough information about the outcome.

The new protocol departs from the sparse array style, returning the status of each event, including the successfully created ones, along with the timestamp when they were processed by the TigerBeetle cluster.

Applications can now benefit from knowing the timestamp assigned to a successfully created Account or Transfer, while also handling alternative paths more efficiently by knowing when validation occurred for those that couldn’t be created.

The enums CreateAccountResult and CreateTransferResult were renamed to CreateAccountStatus and CreateTransferStatus, and the status code ok was renamed to created.

This makes it explicit whether an event became part of the database state (created and exists) or not. By removing the duality of ok and errors, applications can handle results more clearly according to their policies, since some outcomes might not be considered a failure by application logic — for example, a Transfer not being created due to balance checks or pending timeouts isn’t necessarily an error.

Likewise, the exists status now reports the same timestamp returned by created, allowing the application to treat both cases consistently.

The result types CreateAccountsResult and CreateTransfersResult were renamed to the singular form, CreateAccountResult and CreateTransferResult.

// Before:
pub const CreateAccountsResult = extern struct {
    index: u32,
    result: CreateAccountResult,
};

// After:
pub const CreateAccountResult = extern struct {
    timestamp: u64,
    status: CreateAccountStatus,
    reserved: u32 = 0,
};
// Before:
pub const CreateTransfersResult = extern struct {
    index: u32,
    result: CreateTransferResult,
};

// After:
pub const CreateTransferResult = extern struct {
    timestamp: u64,
    status: CreateTransferStatus,
    reserved: u32 = 0,
};

Query limits.

The previous API did not validate the maximum range of the fields AccountFilter.limit and QueryFilter.limit. Values up to 2^32 - 1 were accepted, and the TigerBeetle cluster was responsible for capping the number of results to fit the message size.

Now the TigerBeetle client enforces a valid limit and rejects requests with limits greater than the maximum batch size, returning the too_much_data error code.

This is the same behavior as when, for example, create_accounts or create_transfers are called with more than 8189 events.

The operations query_accounts, query_transfers, get_account_transfers, and get_account_balances are affected.

Client breaking changes

Along with the new result types, some client libraries have changed the API to be more idiomatic, for naming consistency, or even due to bug fixes in the previous API.

See below is a list of API changes specific to each client library:

.NET

.NET Client breaking changes

The TigerBeetle .NET Client 0.17.0 introduced the following breaking changes:

  • The enum types CreateAccountResult and CreateTransferResult, with the status codes for the create_accounts and create_transfers operations respectively, were renamed to CreateAccountStatus and CreateTransferStatus.

    The enum value Ok, present in both enum types, was replaced by the new status code Created, which indicates that the event was successfully created.

    Type Before After
    Enum CreateAccountResult CreateAccountStatus
    Enum Value CreateAccountResult.Ok CreateAccountStatus.Created
    Enum CreateTransferResult CreateTransferStatus
    Enum Value CreateTransferResult.Ok CreateTransferStatus.Created
  • The result types CreateAccountsResult and CreateTransfersResult were renamed to the singular form, CreateAccountResult and CreateTransferResult.

    The property Index was removed, since each result value corresponds to an event in the batch at the same index.

    Additional changes include the new Timestamp property and renaming the Result property to Status, reflecting the change to the associated enums.

    Type Before After
    Struct CreateAccountsResult CreateAccountResult
    Property CreateAccountsResult.Index removed
    Property NA CreateAccountResult.Timestamp
    Property CreateAccountsResult.Result CreateAccountResult.Status
    Struct CreateTransfersResult CreateTransferResult
    Property CreateTransfersResult.Index removed
    Property NA CreateTransferResult.Timestamp
    Property CreateTransfersResult.Result CreateTransferResult.Status
  • Non-batched methods of the Client class that received a single event such as CreateAccount, CreateTransfer, LookupAccount, and LookupTransfer were removed.

    The batched versions that take an array of events such as CreateAccounts, CreateTransfers, LookupAccounts, and LookupTransfers remain unchanged.

  • New exceptions were introduced for conditions that can be handled by the application. The PacketStatus enum is now internal and the RequestException was made abstract.

    The client can be explicitly closed by calling Client.Close(), whereas previously the only way to close a client was through Client.Dispose(). Interacting with a closed client now throws a ClientClosedException instead of an ObjectDisposedException.

    Type Before After
    Enum PacketStatus removed
    Exception RequestException removed
    Method added Client.Close()
    Exception ClientClosedException
    Exception ClientEvictedException
    Exception ClientReleaseException
    Exception TooMuchDataException

Example:

Before:

CreateTransfersResult[] transferErrors = client.CreateTransfers(transfers);
if (transferErrors.Length > 0) {
    // Error handling ...
}

After:

CreateTransferResult[] transferResults = client.CreateTransfers(transfers);
Assert.AreEqual(transferResults.Length, transfers.Length);
foreach(CreateTransferResult result in transferResults)
{
    switch(result.Status)
    {
        case CreateTransferStatus.Created:
        case CreateTransferStatus.Exists:
            // Successfully created.
            break;
        default:
            // Could not be created.
            break;
    }
}

For more details, please refer to the .NET client reference page.


Go

Go Client breaking changes

The TigerBeetle Go Client 0.17.0 introduced the following breaking changes:

  • The enum types CreateAccountResult and CreateTransferResult, with the status codes for the create_accounts and create_transfers operations respectively, were renamed to CreateAccountStatus and CreateTransferStatus.

    The enum values AccountOK and TransferOK, were replaced by the new status codes AccountCreated and TransferCreated, which indicates the event was successfully created by the operation.

    Type Before After
    Enum CreateAccountResult CreateAccountStatus
    Enum Value AccountOK AccountCreated
    Enum CreateTransferResult CreateTransferStatus
    Enum Value TransferOK TransferCreated
  • The result types AccountEventResult and TransferEventResult were renamed to CreateAccountResult and CreateTransferResult.

    The field Index was removed, since each result value corresponds to an event in the batch at the same index.

    Additional changes include the new Timestamp field and renaming the Result field to Status, reflecting the change to the associated enums.

    Type Before After
    Type AccountEventResult CreateAccountResult
    Field AccountEventResult.Index removed
    Field NA CreateAccountResult.Timestamp
    Field AccountEventResult.Result CreateAccountResult.Status
    Type TransferEventResult CreateTransferResult
    Field TransferEventResult.Index removed
    Field NA CreateTransferResult.Timestamp
    Field TransferEventResult.Result CreateTransferResult.Status
  • The types and errors packages were removed, consolidating all definitions under the root tigerbeetle_go package.

    The Err types were removed in favor of simple value declarations for error codes, allowing the use of idiomatic constructions such as errors.Is(err, ErrTooMuchData).

  • Conversions between UInt128 and big.Int now return and accept a pointer to a big integer *big.Int, making the API more idiomatic.

    Type Before After
    Function BigInt() big.Int BigInt() *big.Int
    Function BigIntToUint128(value big.Int) Uint128 BigIntToUint128(value *big.Int) Uint128

Example:

Before:

import (
    . "github.com/tigerbeetle/tigerbeetle-go"
    . "github.com/tigerbeetle/tigerbeetle-go/pkg/types"
)

var transferErrors []TransferEventResult
var err error

transferErrors, err = client.CreateTransfers(transfers);
if err != nil {
    // Request error ...
}
if len(transferErrors) > 0 {
    // Error handling ...
}

After:

import (
    . "github.com/tigerbeetle/tigerbeetle-go"
)

var transferResults []CreateTransferResult
var err error

transferResults, err = client.CreateTransfers(transfers);
if err != nil {
    // Request error ...
}
for _, result := range transferResults {
    switch result.Status {
    case TransferCreated, TransferExists:
        // Successfully created.
    default:
        // Could not be created.
    }
}

For more details, please refer to the Go client reference page.


Java

Java Client breaking changes

The TigerBeetle Java Client 0.17.0 introduced the following breaking changes:

  • The enum types CreateAccountResult and CreateTransferResult, with the status codes for the create_accounts and create_transfers operations respectively, were renamed to CreateAccountStatus and CreateTransferStatus.

    The enum value Ok, present in both enum types, was replaced by the new status code Created, which indicates that the event was successfully created.

    Type Before After
    Enum CreateAccountResult CreateAccountStatus
    Enum Value CreateAccountResult.Ok CreateAccountStatus.Created
    Enum CreateTransferResult CreateTransferStatus
    Enum Value CreateTransferResult.Ok CreateTransferStatus.Created
  • The result types CreateAccountResultBatch and CreateTransferResultBatch, had the getIndex() property removed, since each result value corresponds to one event in the batch at the same index.

    Additional changes include the new getTimestamp() property and renaming the getResult() property to getStatus(), reflecting the change to the associated enums.

    Type Before After
    Method CreateAccountResultBatch.getIndex() removed
    Method NA CreateAccountResultBatch.getTimestamp()
    Method CreateAccountResultBatch.getResult() CreateAccountResultBatch.getStatus()
    Method CreateTransferResultBatch.getIndex() removed
    Method NA CreateTransferResultBatch.getTimestamp()
    Method CreateTransferResultBatch.getResult() CreateTransferResultBatch.getStatus()
  • All the blocking methods of the Client class (such as createAccounts, createTransfers, and others) may throw the checked exception InterruptedException to signal that the waiting thread was interrupted by the Java environment. The non-blocking versions of the same methods that return a CompletableFuture<T> remain unchanged.

  • New exceptions were introduced for conditions that can be handled by the application. The PacketStatus enum is now internal and the RequestException was removed.

    All operations throw ClientClosedException instead of IllegalStateException if the client is closed.

    Type Before After
    Enum PacketStatus removed
    Exception RequestException abstract class
    Exception ClientClosedException extends RequestException
    Exception ClientEvictedException
    Exception ClientReleaseException
    Exception TooMuchDataException

Example:

Before:

CreateTransferResultBatch transferErrors = client.createTransfers(transfers);
if (transferErrors.getLength() > 0) {
    // Error handling ...
}

After:

try {
    CreateTransferResultBatch transferResults = client.createTransfers(transfers);
    assert transferResults.getLength() == transfers.getLength();
    while (transferResults.next()) {
        switch (transferResults.getStatus()) {
            case Created:
            case Exists:
                // Successfully created.
                break;
            default:
                // Could not be created.
                break;
        }
    }
} catch (InterruptedException exception) {
    // The thread was interrupted.
}

For more details, please refer to the Java client reference page.


Node.js

Node.js Client breaking changes

The TigerBeetle Node.js Client 0.17.0 introduced the following breaking changes:

  • The enum types CreateAccountError and CreateTransferError, with the status codes for the create_accounts and create_transfers operations respectively, were renamed to CreateAccountStatus and CreateTransferStatus.

    The enum value ok, present in both enum types, was replaced by the new status code created, which indicates that the event was successfully created.

    Type Before After
    Enum CreateAccountError CreateAccountStatus
    Enum Value CreateAccountError.ok CreateAccountStatus.created
    Enum CreateTransferError CreateTransferStatus
    Enum Value CreateTransferError.ok CreateTransferStatus.created
  • The result types CreateAccountsError and CreateTransfersError were renamed to CreateAccountResult and CreateTransferResult.

    The field index was removed, since each result value corresponds to an event in the batch at the same index.

    Additional changes include the new timestamp field and renaming the result field to status, reflecting the change to the associated enums.

    Type Before After
    Type CreateAccountsError CreateAccountResult
    Field CreateAccountsError.index removed
    Field NA CreateAccountResult.timestamp
    Field CreateAccountsError.result CreateAccountResult.status
    Type CreateTransfersError CreateTransferResult
    Field CreateTransfersError.index removed
    Field NA CreateTransferResult.timestamp
    Field CreateTransfersError.result CreateTransferResult.status
  • New error type RequestError was introduced for conditions that can be handled by the application. Match the RequestError.code property against the constants defined in ErrorCodes to determine the specific failure.

    Type Before After
    Type ErrorCodes
    Error RequestError

Example:

Before:

const transferErrors: CreateTransfersError[] = await client.createTransfers(transfers);
if (transferErrors.length > 0) {
    // Error handling ...
}

After:

const transferResults: CreateTransferResult[] = await client.createTransfers(transfers);
assert.strictEqual(transferResults.length, transfers.length);
for (const result of transferResults) {
    switch (result.status) {
        case CreateTransferStatus.created:
        case CreateTransferStatus.exists:
            // Successfully created.
            break;
        default:
            // Could not be created.
            break;
    }
}

For more details, please refer to the Node.js client reference page.


Python

Python Client breaking changes

The TigerBeetle Python Client 0.17.0 introduced the following breaking changes:

  • The enum types CreateAccountResult and CreateTransferResult, with the status codes for the create_accounts and create_transfers operations respectively, were renamed to CreateAccountStatus and CreateTransferStatus.

    The enum value OK, present in both enum types, was replaced by the new status code CREATED, which indicates that the event was successfully created.

    Type Before After
    Enum CreateAccountResult CreateAccountStatus
    Enum Value CreateAccountResult.OK CreateAccountStatus.CREATED
    Enum CreateTransferResult CreateTransferStatus
    Enum Value CreateTransferResult.OK CreateTransferStatus.CREATED
  • The result types CreateAccountsResult and CreateTransfersResult were renamed to the singular form, CreateAccountResult and CreateTransferResult.

    The field index was removed, since each result value corresponds to an event in the batch at the same index.

    Additional changes include the new timestamp field and renaming the result field to status, reflecting the change to the associated enums.

    Type Before After
    Type CreateAccountsResult CreateAccountResult
    Field CreateAccountsResult.index removed
    Field NA CreateAccountResult.timestamp
    Field CreateAccountsResult.result CreateAccountResult.status
    Type CreateTransfersResult CreateTransferResult
    Field CreateTransfersResult.index removed
    Field NA CreateTransferResult.timestamp
    Field CreateTransfersResult.result CreateTransferResult.status
  • The constant amount_max was renamed to AMOUNT_MAX.

  • New exceptions were introduced for conditions that can be handled by the application. The PacketStatus enum is now internal and the PacketError exception was removed.

    Type Before After
    Enum PacketStatus removed
    Exception PacketError removed
    Exception ClientEvictedError
    Exception ClientReleaseTooLowError
    Exception ClientReleaseTooHighError
    Exception TooMuchDataError
  • Removed all default initialization values from the types AccountFilter and QueryFilter.

Example:

Before:

transfer_errors = client.create_transfers(transfers)
if len(transfer_errors) > 0:
    # Error handling ...

After:

transfer_results = client.create_transfers(transfers)
assert len(transfer_results) == len(transfers)
for result in transfer_results:
    if result.status == tb.CreateAccountResult.CREATED or \
       result.status == tb.CreateAccountResult.EXISTS:
        # Successfully created.
    else:
        # Could not be created.

For more details, please refer to the Python client reference page.


Rust

Rust Client breaking changes

The TigerBeetle Rust Client 0.17.0 also introduced the new API. However, the Rust client is not yet publicly available on Crates.io at the time of this release, so they are not considered breaking changes.

For more details, please refer to the Rust client reference page.

0.16.33

Oldest supported client version is 0.16.4

Please make sure that all of your clients are running on at 0.16.4 or newer before upgrading to this release!

0.16.4

Transient Failures

Clients have the strong guarantee that a Transfer.id that has once failed due to a transient error code will never succeed again if retried.

Transient failures occur when semantically valid transfers fail due to reasons that depend exclusively on the database status. For example, when an account does not have enough credits to fulfill the transfer.

Please refer to the documentation for a complete list of all transient failures.

As of 0.16.4:

  • New precedence order for the create_transfers and create_accounts error codes. The idempotency checks (e.g., all exists_* cases) are now validated prior to the semantical checks.

    For example, when submitting a transfer with the id of an existing one, clients might receive exists_with_different_<field_name> instead of <field_name>_must_not_be_zero.

    This is not a breaking API change and affects all supported client versions.

  • create_transfers now returns exists_with_different_ledger Reflecting the new precedence order change.

    This is a breaking API change which is gated in the state machine by the client’s release. Clients of previous versions will receive transfer_must_have_the_same_ledger_as_accounts instead.

  • Added a new result code id_already_failed. It is returned by create_transfers when the Transfer.id was already used in a previous attempt that resulted in a transient failure.

    This is a breaking API change which is gated in the state machine by the client’s release. Clients of previous versions will be able to successfully create transfers submitted with an id that previously failed, since it passes all validations.

0.16.0

Zero-amount transfers

Zero-amount transfers are now permitted.

This is a breaking API change which is gated in the state machine by the client’s release.

As of 0.16.0:

  • Clients no longer return amount_must_not_be_zero to create_transfers.

  • Balancing transfers no longer use amount=0 as a sentinel value to represent “transfer as much as possible”. For that purpose, use AMOUNT_MAX (exact constant name depends on client implementation) instead.

  • Post-pending transfers no longer use amount=0 as a sentinel value to represent “transfer full pending amount”. For that purpose, use AMOUNT_MAX instead. In 0.16.0, sending a post-pending transfer with amount=0 will successfully post amount=0, voiding the remainder (i.e. voiding the whole pending amount).

Edit this page