---
id: ADR-ACC-PRD-005
title: Versions Detect Stale Writes; Product Locks Serialize Local Changes
product_area: accounting
module: products
revision: 3
status: proposed
design_intent: proposed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
decision: Existing replacements and product lifecycle actions compare read versions, product and setup writers
  share a product lock, bulk writers acquire those locks in key order, and kind defaults use their own rows
  without versioned deletion.
constrains:
- DOM-ACC-PRD-001
- DOM-ACC-PRD-004
- STATE-ACC-PRD-001
- STATE-ACC-PRD-003
- SVC-ACC-PRD-products
- WF-ACC-PRD-001
- WF-ACC-PRD-005
origin: none
alternatives:
- option: Use version checks without a common product lock.
  why_not: A setup could validate against a price changed before its transaction finishes.
- option: Accept whichever request arrives last.
  why_not: A later request could silently overwrite someone else's edits.
consequences:
- Recognized console conflicts offer Reload.
- Remote template latency lengthens the product lock.
- Key uniqueness resolves competing creates.
supersedes: []
evidence:
- 'services-accounting at f47cb263: modules/products/services/persistence/products.ts (lockProduct, lockProductForAccounting,
  lockProductsInIdOrder); product-accounting-setups.ts.'
---

# Versions Detect Stale Writes; Product Locks Serialize Local Changes

## Context

Setup checks read product pricing, and deletion checks setup protection. Row locks stabilize those reads while versions detect stale client edits.

## Decision

Existing replacements and product lifecycle actions compare read versions, product and setup writers share a product lock, bulk writers acquire those locks in key order, and kind defaults use their own rows without versioned deletion.

## Alternatives Considered

Use version checks without a common product lock. A setup could validate against a price changed before its transaction finishes.

Accept whichever request arrives last. A later request could silently overwrite someone else's edits.

## Consequences

These locks protect one product's local mutation boundary. They do not serialize the whole bundle graph, couple tax-default edits to products, or revalidate shares after a product price change.
