Magento2 Content Staging

In this Tutorial we will cover the below topics

  • What is Content Staging
  • How Content Staging Works
  • Content Staging Cron

What is Content Staging

As a Merchant, say you want to provide discount 20% to all the products on Black Friday.

So what you can do is, On Black Friday Early Morning login to the admin portal and enable / create the respective promotion and again wake up the next morning and disable it 🙂
This operation is too risky, inconvenient and also not manageable for many reason.

Wouldn’t be nice if there is way where you can create promotion page, create catalog rule, cart rule etc. way before Black Friday where you can preview it test it and by some kind of magic it got enabled automatically on Black Friday and then got disabled once the black Friday is over!!!.

Yes this is possible now with Content Staging (Exclusive feature only in Adobe Commerce)

Content Staging gives your business team the ability to easily create, preview, and schedule a wide range of content updates for your store directly from the Admin.

Using Content Staging Schedules (which we will see later) you now have the ability to create a content, campaign etc and set the data and time for that content to be visible to the customers. The below entities are supported for Content Staging.

  • Products
  • Categories
  • Catalog Price Rules
  • Cart Price Rules
  • CMS Pages
  • CMS Blocks
  • Widgets

How Content Staging Works

To understand how content staging works lets first find out how the data for the content staging schedules are stored. As we saw in the earlier para content staging is supported for several entity types. The entity data is usually stored in the EAV entity tables.

For this example lets consider the Product Entity. The same behavior will be applicable for the other entity types as well.

When a Product is created We have the below data stored in the catalog_product_entity table, and the product attribute data is stored in the Product Entity Eav tables.

SELECT* FROM catalog_product_entity WHERE sku = 'HM0564314020188005';

For the purpose of Content Staging Magento has introduced three new columns in all the entity tables

  • row_id,
  • created_id
  • updated_in

we will discuss more on how these columns helps to achieve content staging. These 3 columns will not her there in the Community Version.


The row_id is the primary key and the Auto Increment column which means this data here will be unique. All the EAV tables where the product data gets stored contains the relation to catalog_product_entity with row_id and not with the entity_id.

Consider the below relation on how the product name is stored in the catalog_product_entity_varchar table.

SELECT * FROM catalog_product_entity_varchar
WHERE attribute_id = (SELECT attribute_id 
FROM eav_attribute
WHERE attribute_code = 'name' AND entity_type_id = 4)
AND store_id = 1
AND row_id IN(
SELECT row_id 
FROM catalog_product_entity 
WHERE sku = 'HM0564314020188005');


The column to store the Product ID.

created_in & updated_at

These two columns together will be used to find the correct row_id for the respective product any given time. When you created a new product we will always have created_in = 1 and updated_at = 2147483647 ( January 19, 2038)

Now, Lets Create a Schedule for this Product and see what data are getting update in these columns.

As a example we are going the change the name of the Product for tomorrow and day after tomorrow. Today the name of the product is “Iphone 12” and from tomorrow and day after it will be “Iphone 12 – Big Discount” and then beyond that the name will be reverted back to “Iphone 12”

Now lets see how this data is stored.

For the same sku now we have three rows in the catalog_product_entity table. Here entity_id is the same but the row_id differs.

Also if we look at the eav tables we could see 3 entries for each product.

Not only the data that we modified in fact we will have the complete data duplicated / modified based on the no of schedules that you create.

Now that we know how the data is stored, Lets see how the correct data is fetched on the respective data or time.

For every select query, Magento by default appends the below where condition for all the entities that supports Content staging to identify the correct row_id of that respective entity.

12AND(created_in <= '1643284740') AND(updated_in > '1643284740')

This happens in the class \Magento\Staging\Model\Select\FromRenderer

In our case, the query becomes

created_in and updated_in will get updated based on the current date and time to do so magento involves “staging_update” and “flag” tables.

In Short, Based on the date that you are in this query will get the correct row_id of the respective product.

Once you have the row id then you can get all the relevant data for that row_id from the EAV tables for any given schedule.

Content Staging Cron

Now that we know how the data for the content staging is stored and fetched. Lets see what role does the cron plays in content Staging. The below crons are defined for the purpose of content staging.

<group id="staging">
    <job name="staging_apply_version" instance="Magento\Staging\Model\StagingApplier" method="execute">
        <schedule>* * * * *</schedule>
    <job name="staging_remove_updates" instance="Magento\Staging\Model\Update\Cleaner" method="execute">
        <schedule>* * * * *</schedule>
    <job name="staging_synchronize_entities_period" instance="Magento\Staging\Model\SynchronizeEntityPeriod" method="execute">
        <schedule>* * * * *</schedule>

Magento Indexing plays a vital role in processing the raw data and store it in appropriate tables for easy fetching. i.e For the frontend most of the data is fetched from the index table. For Ex lets say you wanted to create a Catalog Rule with 10% discount site wide, Once the rule is created this 10% discount will not be available for the customers untill the "catalogrule_rule" indexer executed for this rule.

Now lets create a Catalog Rule "10 % Discount on Christmas Day" and scheduled it to enable it on 25th Dec, this rule will become active on Christmas day, but unless and until "catalogrule_rule" indexer gets executed for this rule there will be no discount provided to the customer. So to trigger the relevant indexer on the scheduled data and time Content Staging Cron is used.


This cron is responsible for looping through all the staging entity types and executing the relevant entity type appliers.

Before we execute the entity type applier we need to find if there is any valid entity ids for that entity type, This is done in this method

\Magento\Staging\Model\ResourceModel\Db\GetNotIndexedEntities::execute which generated the below query

SELECT entity_table.entity_id FROM catalog_product_entity AS entity_table WHERE (created_in > $lastProcessedVersionId ) AND (created_in <=$currentVersionId)

These response will give us which entity ids (ProductIds or Rule Ids) that needs to be re-indexed. These entity ids are then processed by the relevant entity type applier.


Entity TypeApplier

Leave a Reply

Your email address will not be published.