[id='invalidation-{context}']
= Invalidation Mode
You can use {brandname} in invalidation mode to optimize systems that perform
high volumes of read operations. A good example is to use invalidation to
prevent lots of database writes when state changes occur.

This cache mode only makes sense if you have another, permanent store for your data such
as a database and are only using {brandname} as an optimization in a read-heavy system,
to prevent hitting the database for every read.
If a cache is configured for invalidation, every time data is changed in a cache, other
caches in the cluster receive a message informing them that their data is now stale and
should be removed from memory and from any local store.

.Invalidation mode
image::clustering-invalidation.svg[align="center", title="Invalidation mode"]

Sometimes the application reads a value from the external store and wants to write it to
the local cache, without removing it from the other nodes.
To do this, it must call `Cache.putForExternalRead(key, value)` instead of
`Cache.put(key, value)`.

Invalidation mode can be used with a shared cache store.
A write operation will both update the shared store, and it would remove the stale values
from the other nodes' memory.
The benefit of this is twofold: network traffic is minimized as invalidation messages are
very small compared to replicating the entire value, and also other caches in the cluster
look up modified data in a lazy manner, only when needed.

NOTE: Never use invalidation mode with a *local* store.
The invalidation message will not remove entries in the local store, and some
nodes will keep seeing the stale value.

An invalidation cache can also be configured with a special cache loader, `ClusterLoader`.
When `ClusterLoader` is enabled, read operations that do not find the key on the local
node will request it from all the other nodes first, and store it in memory locally.
In certain situation it will store stale values, so only use it if you have a high
tolerance for stale values.

Invalidation mode can be synchronous or asynchronous.
When synchronous, a write blocks until all nodes in the cluster have evicted the stale
value. When asynchronous, the originator broadcasts invalidation messages but doesn't
wait for responses.
That means other nodes still see the stale value for a while after the write completed on
the originator.

Transactions can be used to batch the invalidation messages.
Transactions acquire the key lock on the primary owner.
To find more about how primary owners are assigned, please read the
link:#key_ownership[Key Ownership] section.

* With pessimistic locking, each write triggers a lock message, which is
broadcast to all the nodes.
During transaction commit, the originator broadcasts a one-phase prepare message
(optionally fire-and-forget) which invalidates all affected keys and releases the locks.

* With optimistic locking, the originator broadcasts a prepare message, a commit message,
and an unlock message (optional).
Either the one-phase prepare or the unlock message is fire-and-forget,
and the last message always releases the locks.
