Adobe Commerce Architect Master study materials
Adobe Commerce Architect Master study resources

Multi-Store Product Data Model for Regional Attributes

Adobe Commerce Architect Master · Put your knowledge to work in context.

All case studies

Multi-Store Product Data Model for Regional Attributes

A retailer sells in 5 countries. Products need: a global SKU and name, per-country localized descriptions (5 languages), per-country warranty text, and a per-country is_sellable flag. They also need a global launch_date and a per-country launch_date_override that is usually empty. Current implementation: every field is a global attribute, so descriptions are duplicated per store view and the catalog is 3x larger than necessary. Editors complain they re-enter warranty text for every store view. Reporting needs to filter products by country sellability. The catalog has 250k products.

1. Classify each field by scope (global/website/store) and justify. Identify which fields must NOT be store-scoped and why.

Read the worked answer

Scope assignment:

  • sku, name (if truly global), launch_date: global - one value, no duplication. sku must be global for identity.
  • Localized descriptions (5 languages): store view - text differs by language, which maps to store view. This is the legitimate store-scope case.
  • warranty_text, is_sellable, launch_date_override: website - these vary by country, and country maps to website (or store group), not store view. Scoping them to store view forces re-entry per language within a country.

Why not store-scope warranty/sellability: a country with 2 languages would duplicate the same warranty text twice, and is_sellable would need to be consistent across languages - store scope invites drift. Website scope gives one authoritative value per country, editable once.

Caveat: if a country has multiple websites (e.g., B2B vs B2C in same country), website scope splits them; then use store-group scope or a country attribute. Confirm the website↔country mapping before finalizing.

2. Design the schema to eliminate the 3x bloat and support reporting on country sellability. Address the `launch_date_override` pattern.

Read the worked answer

Use native attribute scoping rather than one global column:

  • Global fields → catalog_product_entity or a global EAV table (catalog_product_entity_varchar with store_id=0).
  • Store-scoped descriptions → catalog_product_entity_text rows with store_id per language.
  • Website-scoped warranty/sellability/override → catalog_product_entity_* rows with store_id = 0 but a website-scoped attribute so Commerce writes per-website values into catalog_product_entity_* keyed by website via the scoped indexer. (Native EAV store_id is store-view; for website scope you rely on attribute scope=website and the flat/index tables carrying store_id per website's default store.)

For the override pattern: do not store a duplicate launch_date_override per country when usually empty. Instead keep global launch_date and a website-scoped launch_date_override; at read time resolve COALESCE(override, global). This keeps nulls sparse.

For reporting: build a flat index table catalog_product_flat_* or a custom reporting table (product_country_sellability) populated by an indexer, with columns (product_id, website_id, is_sellable, effective_launch_date). Report against that, not EAV joins - 250k products × 5 countries is fine in a flat table, painful in EAV.

3. Editors still re-enter warranty text per store view. What is wrong and how do you correct it without a data migration disaster?

Read the worked answer

If warranty is still duplicated per store view, the attribute is still scope=store (or the admin UI is configured that way). Changing an attribute's scope in Commerce drops its existing data - scope changes are destructive. So you cannot simply flip the scope.

Safe path:

  1. Create a new website-scoped attribute warranty_text_ws.
  2. Write a migration that, for each product, picks the canonical value per website (e.g., the default store view's value) and populates the new attribute per website.
  3. Update templates, GraphQL/REST schema, and any code reading the old attribute.
  4. Verify, then deprecate/remove the old attribute.

Do this in a maintenance window with a dry run on a catalog copy. Back up catalog_product_entity_text first. Never alter scope on a live attribute with 250k rows.