Skip to main content
Version: Next

Versioning

General

Pimcore versions all documents, assets, and data objects automatically. Every save creates a new version with no limit on retained versions unless configured otherwise.

Open the Versions tab on any element to view the change history, compare revisions, and restore or publish a specific version.

Object versions changeslistObject versions changeslistObject versions changeslist

Settings

Configure the number of retained versions and the retention period in the system settings for Documents, Assets, and Objects within Pimcore Studio.

Objects version history settingsObjects version history settingsObjects version history settings

Stack Trace

Pimcore stores a stack trace in the database for each version. Disable this per element type:

pimcore:
assets:
versions:
disable_stack_trace: true
documents:
versions:
disable_stack_trace: true
objects:
versions:
disable_stack_trace: true

A maintenance job (VersionsCleanupStackTraceDbTask) automatically removes stack traces older than 7 days.

Version Storage

Every version stores metadata and, if present, binary data. Since version data can grow quickly, Pimcore provides three storage strategies.

Configuration

Filesystem

This is the default. Store version data on the filesystem using FileSystemStorageAdapter:

Pimcore\Model\Version\Adapter\VersionStorageAdapterInterface:
public: true
alias: Pimcore\Model\Version\Adapter\FileSystemVersionStorageAdapter

Pimcore\Model\Version\Adapter\FileSystemVersionStorageAdapter: ~

Database

Store version data in a database using DatabaseVersionStorageAdapter. Pass a configured Doctrine connection as an argument - this allows using a dedicated database for version data only:

Pimcore\Model\Version\Adapter\VersionStorageAdapterInterface:
public: true
alias: Pimcore\Model\Version\Adapter\DatabaseVersionStorageAdapter

Pimcore\Model\Version\Adapter\DatabaseVersionStorageAdapter:
arguments:
$databaseConnection: '@doctrine.dbal.versioning_connection'

The target database needs a versionsData table. Create it with:

CREATE TABLE `versionsData` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`cid` int(11) unsigned DEFAULT NULL,
`ctype` enum('document','asset','object') DEFAULT NULL,
`metaData` longblob DEFAULT NULL,
`binaryData` longblob DEFAULT NULL,
PRIMARY KEY (`id`)
)

Delegate

Route version data to different storage backends based on size using DelegateVersionStorageAdapter. When metadata or binary data exceeds the configured byteThreshold, the fallback adapter handles storage:

Pimcore\Model\Version\Adapter\VersionStorageAdapterInterface:
public: true
alias: Pimcore\Model\Version\Adapter\DelegateVersionStorageAdapter

Pimcore\Model\Version\Adapter\DelegateVersionStorageAdapter:
public: true
arguments:
$byteThreshold: 1000000
$defaultAdapter: '@Pimcore\Model\Version\Adapter\DatabaseVersionStorageAdapter'
$fallbackAdapter: '@Pimcore\Model\Version\Adapter\FileSystemVersionStorageAdapter'

Pimcore\Model\Version\Adapter\FileSystemVersionStorageAdapter: ~

Pimcore\Model\Version\Adapter\DatabaseVersionStorageAdapter:
arguments:
$databaseConnection: '@doctrine.dbal.versioning_connection'

In this example, version data up to 1,000,000 bytes goes to the database; larger data falls back to the filesystem.

Disable Versioning for the Current Process

For bulk operations like imports or third-party synchronizations, disable versioning temporarily:

\Pimcore\Model\Version::disable(); // disable versioning for the current process
\Pimcore\Model\Version::enable(); // re-enable versioning for the current process

This only affects the current PHP process. The setting is not persisted and does not affect other requests.

Coauthor Information

In addition to the user, every version can carry an optional coauthor: a second, machine-readable attribution for saves that a system performed together with the user, for example an AI agent acting on the user's behalf.

A coauthor consists of two fields, both stored on the version:

FieldMeaningExample
coauthorTypeShort machine string categorizing the coauthoragent
coauthorFree-form identifier of the coauthorproduct-data-agent

Versions without a coauthor store null in both fields. The Versions tab in Pimcore Studio shows a "Co-authored by" tag on stamped versions.

Setting a Coauthor

The coauthor context is a container service (Pimcore\Model\Version\CoauthorContextInterface). While the context is active, every newly created version is stamped automatically:

$coauthorContext = \Pimcore::getContainer()->get(\Pimcore\Model\Version\CoauthorContextInterface::class);

// stamp a single save
$coauthorContext->withCoauthor('automation', 'my-importer', fn () => $object->save());

// or stamp everything until clear() is called
try {
$coauthorContext->set('automation', 'my-importer');
$object->save();
$anotherObject->save();
} finally {
$coauthorContext->clear();
}

In services, inject CoauthorContextInterface instead of accessing the container directly.

Setting the coauthor explicitly via $version->setCoauthorType() / $version->setCoauthor() always wins over the context. Only newly created versions are stamped; re-saving an existing version never changes its coauthor.

Disable Coauthor Stamping for the Current Process

$coauthorContext->disable(); // suppress stamping, the context values are kept
$coauthorContext->enable(); // resume stamping

This only affects the current PHP process, analogous to Version::disable() above.

Working with the PHP API

When saving elements programmatically, set userModification so the correct user appears in version history. Set it to 0 to display system as the user:

$object->setUserModification(0);
$object->save();

Retrieve a Previous Version

$versions = $currentObject->getVersions();
$previousVersion = $versions[count($versions)-2];
$previousObject = $previousVersion->getData();