Whenever an object is fetched from the database or created by the user and registered with Cayenne, it is automatically cached. Accessing this object later (e.g. when traversing a relationship from another object, or doing a lookup by primary key via DataObjectUtils) will not incur an overhead of extra database access.
Very often there's more than one ObjectContext working over the same Cayenne stack. E.g. in a web application each user session may have its own ObjectContext. If one of the contexts commits its changes, Cayenne automatically updates copies of each modified object across all contexts ("copies" mean context-specific instances of objects with the same ObjectId). So all committed object changes become immediately visible to all contexts. If there's more than one Cayenne stack running (e.g. if the application is clustered across multiple JVMs), there are ways to notify other stacks about the object changes. This can be setup in the Modeler. However full synchronization results in too much network traffic and CPU consumption, and is usually avoided in favor of the query cache approach described elsewhere in this chapter.
Cayenne ensures that the memory allocated to caching does not grow indefinitely. A cache shared between ObjectContexts has a fixed upper limit. 10000 is the default maximum number of entries, which can be changed in the Modeler. A cache attached to each ObjectContext (also referred to as "local cache" elsewhere in this chapter), which only stores the objects that were accessed via this context, has no upper limit. However it uses weak references to the cached committed objects, so they are automatically purged from cache when the application runs low on memory.
Object caching happens behind the scenes, so the only case when users need to worry about object cache is when an object gets stale and needs to get refreshed. Here are the strategies for refreshing a single stale object: