Business

5 min read

How Broadleaf Handles Concurrent Merchandising Edits Without Locking Records

Elbert Bautista

Written by Elbert Bautista

Published on Sep 22, 2026

code changes

Two merchandisers, same product, same afternoon. One is fixing a price. The other is rewriting the description for a seasonal campaign. On a platform that locks rows, the second save either waits on the first or overwrites it. Broadleaf does neither. Each change lands in its own sandbox, and when the two eventually promote toward production, they merge field by field instead of colliding.

That's the short version. Most vendors say "sandboxing" and mean a staging environment with a fancier name. Broadleaf provides a real data model with versioning mechanics underneath for those evaluating commerce platforms that require handling multiple people editing the same catalog at once.

The Problem With Locking a Catalog Record

Standard optimistic locking, the kind JPA gives you with @Version, checks a version number on the whole entity. Two users load the same product. One saves. The version increments. The second save fails the version check, even if the two edits touched completely different fields.

That's fine for a low-contention table. It's the lazy version of concurrency control on a shared catalog, where a single product record might have a merchandiser touching price, a copywriter touching description, and an import job touching inventory count, all inside the same hour. Entity-level locking treats all three as one conflict.

Sandboxes Are Isolated Instances

Broadleaf's answer is what the docs call Data Workflow, better known internally as sandboxing. A domain class marked with @TrackableExtension({SANDBOX, CATALOG}) and a TrackingListener doesn't lock anything on save. Instead, editing a production record creates a new copy, scoped to the editing user's sandbox. Production stays untouched until that sandbox change gets promoted.

Reads narrow automatically to the closest applicable version. If you have a sandbox copy of a product, your fetch results return your sandbox version instead of production, with no special query logic required on the calling code's part. 

Merges Happen Field by Field, Not Entity by Entity

When sandbox changes get promoted toward production, Broadleaf doesn't merge the whole record. It merges ChangeDetail entries, one per field. The price fix and the description rewrite promote independently, because they never touch the same piece of the record.

It also means rejection works at field granularity. An approver can reject the description change and send it back to the copywriter while the price fix keeps moving forward untouched. Try that with a version-number lock on the whole entity.

The Lock Didn't Disappear

So, what stops two competing promotion requests from racing each other and corrupting the transition itself?

Broadleaf's answer lives in a table called BLC_RESOURCE_LOCK. It locks the transition itself, the act of moving a ChangeSummary from one state to the next, long enough to guarantee a promotion message doesn't get processed twice and that two competing transition requests on the same change don't interleave.

Promotion Moves Through Named Transitions

Sandbox state moves through four defined transitions: promote, deploy, revert, and reject. Each one runs over its own Spring Cloud Stream channel, backed by Kafka by default. A WorkflowTransitionHelper applies the accumulated ChangeDetails to a version of the record with higher visibility at each promotion step, and the final promotion, deployment, writes those changes to the production record itself.

Deployment doesn't have to happen immediately. Anyone with deployment permission can schedule it for a future date and time.

Propagation to Child Catalogs Checks for Collisions First

Multi-brand catalogs in Broadleaf are hierarchical: a parent catalog holds shared data, and child catalogs override what's brand-specific. When a deployment happens on a parent record, those changes propagate down to derived records in child catalogs, field by field, the same way promotion works.


If a child catalog already has its own override on a field the parent is propagating, that specific field stops there. Every other, non-colliding field keeps trickling down. A brand that overrode its own description six months ago doesn't lose that override just because the parent catalog's name changed for everyone else.

Where This Model Has Limitations

Two people editing the exact same field on the exact same product at the exact same moment still resolve as last-write-wins. Broadleaf has opted to support field-level merging which solves the common case, different fields, not the rare one.

Sandbox data also accumulates. Every change sitting in a user or approval sandbox, whether it's actively being reviewed or just forgotten, is a live row somewhere until it gets deployed, reverted, or purged. Broadleaf ships a purge process for obsolete sandbox data, but it's an operational job to be aware of.

What This Means If You're Evaluating the Platform

The question worth asking any commerce vendor isn't "do you support multiple editors." The real question is what happens when two of them touch the same product in the same hour, and whether the answer is a lock, a warning, or an actual merge. 

This is the same approval-and-promotion model behind the Merchandising Suite, and the public docs provide a detailed review of the transition handling and collision logic for those wanting to get into the weeds.

Related Resources