Auto-Increment and Sequences

When using a relational database as an event store, Axon relies on an auto-increment value to allow tracking processors to read all events roughly in the order they were inserted. We say "roughly", because "insert-order" and "commit-order" are different things.

While auto-increment values are (generally) generated at insert-time, these values only become visible at commit-time. This means another process may observe these sequence numbers arriving in a different order. While Axon has mechanisms to ensure eventually all events are handled, even when they become visible in a different order, there are limitations and performance aspects to consider.

When a tracking processor reads events, it uses the "global sequence" to track its progress. When events become available in a different order than they were inserted, Axon will encounter a "gap". Axon will remember these "gaps" to verify that data has become available since the last read. These gaps may be the result of events becoming visible in a different order, but also because a transaction was rolled back. It is highly recommended to ensure that no gaps exist because of over eagerly increasing the sequence number. The mechanism for checking gaps is convenient, but comes with a performance impact.

When using a JpaEventStorageEngine, Axon relies on the JPA implementation to create the table structure. While this will work, it is unlikely to provide the configuration that has the best performance for the database engine in use. That is because Axon uses default settings for the @GeneratedValue annotation.

To override these settings, create a file called /META-INF/orm.xml on the classpath, which looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm">
    <mapped-superclass access="FIELD" metadata-complete="false" class="org.axonframework.eventhandling.AbstractSequencedDomainEventEntry">
        <attributes>
            <id name="globalIndex">
                <generated-value strategy="SEQUENCE" generator="myGenerator"/>
                <sequence-generator name="myGenerator" sequence-name="mySequence"/>
            </id>
        </attributes>
    </mapped-superclass>
</entity-mappings>

It is important to specify metadata-complete="false". This indicates this file should be used to override existing annotations, instead of replacing them. For the best results, ensure that the DomainEventEntry table uses its own sequence. This can be ensured by specifying a different sequence generator for that entity only.