diff --git a/vendor/magento/module-catalog/Model/ResourceModel/GetProductTypeById.php b/vendor/magento/module-catalog/Model/ResourceModel/GetProductTypeById.php
new file mode 100644
index 000000000000..bd62fedb457a
--- /dev/null
+++ b/vendor/magento/module-catalog/Model/ResourceModel/GetProductTypeById.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+declare (strict_types=1);
+namespace Magento\Catalog\Model\ResourceModel;
+
+use Magento\Catalog\Api\Data\ProductInterface;
+use Magento\Framework\App\ResourceConnection;
+
+/**
+ * Get product type ID by product ID.
+ */
+class GetProductTypeById
+{
+    /**
+     * @var ResourceConnection
+     */
+    private $resource;
+
+    /**
+     * @param ResourceConnection $resource
+     */
+    public function __construct(
+        ResourceConnection $resource
+    ) {
+        $this->resource = $resource;
+    }
+
+    /**
+     * Retrieve product type by its product ID
+     *
+     * @param int $productId
+     * @return string
+     */
+    public function execute(int $productId): string
+    {
+        $connection = $this->resource->getConnection();
+        $productTable = $this->resource->getTableName('catalog_product_entity');
+
+        $select = $connection->select()
+            ->from(
+                $productTable,
+                ProductInterface::TYPE_ID
+            )->where('entity_id = ?', $productId);
+
+        $result = $connection->fetchOne($select);
+        return $result ?: '';
+    }
+}
diff --git a/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
index 05b645652093..2fb17da354d0 100644
--- a/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
+++ b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/DefaultStock.php
@@ -8,6 +8,7 @@
 
 use Magento\Catalog\Model\ResourceModel\Product\Indexer\AbstractIndexer;
 use Magento\CatalogInventory\Model\Stock;
+use Magento\Framework\App\ObjectManager;
 use Magento\Framework\DB\Adapter\AdapterInterface;
 use Magento\CatalogInventory\Api\StockConfigurationInterface;
 use Magento\CatalogInventory\Model\Indexer\Stock\Action\Full;
@@ -26,22 +27,16 @@
 class DefaultStock extends AbstractIndexer implements StockInterface
 {
     /**
-     * Current Product Type Id
-     *
      * @var string
      */
     protected $_typeId;
 
     /**
-     * Product Type is composite flag
-     *
      * @var bool
      */
     protected $_isComposite = false;
 
     /**
-     * Core store config
-     *
      * @var \Magento\Framework\App\Config\ScopeConfigInterface
      */
     protected $_scopeConfig;
@@ -58,12 +53,15 @@ class DefaultStock extends AbstractIndexer implements StockInterface
     protected $stockConfiguration;
 
     /**
-     * Param for switching logic which depends on action type (full reindex or partial)
-     *
      * @var string
      */
     private $actionType;
 
+    /**
+     * @var GetStatusExpression
+     */
+    private $getStatusExpression;
+
     /**
      * Class constructor
      *
@@ -72,16 +70,21 @@ class DefaultStock extends AbstractIndexer implements StockInterface
      * @param \Magento\Eav\Model\Config $eavConfig
      * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
      * @param string $connectionName
+     * @param \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression|null $getStatusExpression
      */
     public function __construct(
         \Magento\Framework\Model\ResourceModel\Db\Context $context,
         \Magento\Framework\Indexer\Table\StrategyInterface $tableStrategy,
         \Magento\Eav\Model\Config $eavConfig,
         \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
-        $connectionName = null
+        $connectionName = null,
+        \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression $getStatusExpression = null
     ) {
         $this->_scopeConfig = $scopeConfig;
         parent::__construct($context, $tableStrategy, $eavConfig, $connectionName);
+        $this->getStatusExpression = $getStatusExpression ?: ObjectManager::getInstance()->get(
+            \Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression::class
+        );
     }
 
     /**
@@ -251,6 +254,10 @@ protected function _getStockStatusSelect($entityIds = null, $usePrimaryTable = f
             . ' AND mcpei.attribute_id = ' . $this->_getAttribute('status')->getId()
             . ' AND mcpei.value = ' . ProductStatus::STATUS_ENABLED,
             []
+        )->joinLeft(
+            ['css' => $this->getTable('cataloginventory_stock_status')],
+            'css.product_id = e.entity_id',
+            []
         )->columns(
             ['qty' => $qtyExpr]
         )->where(
@@ -292,7 +299,6 @@ protected function _prepareIndexTable($entityIds = null)
      */
     protected function _updateIndex($entityIds)
     {
-        $this->deleteOldRecords($entityIds);
         $connection = $this->getConnection();
         $select = $this->_getStockStatusSelect($entityIds, true);
         $select = $this->getQueryProcessorComposite()->processQuery($select, $entityIds, true);
@@ -300,6 +306,7 @@ protected function _updateIndex($entityIds)
 
         $i = 0;
         $data = [];
+        $savedEntityIds = [];
         while ($row = $query->fetch(\PDO::FETCH_ASSOC)) {
             $i++;
             $data[] = [
@@ -309,6 +316,7 @@ protected function _updateIndex($entityIds)
                 'qty' => (double)$row['qty'],
                 'stock_status' => (int)$row['status'],
             ];
+            $savedEntityIds[] = (int)$row['entity_id'];
             if ($i % 1000 == 0) {
                 $this->_updateIndexTable($data);
                 $data = [];
@@ -317,6 +325,7 @@ protected function _updateIndex($entityIds)
 
         $this->_updateIndexTable($data);
 
+        $this->deleteOldRecords(array_diff($entityIds, $savedEntityIds));
         return $this;
     }
 
@@ -376,21 +385,7 @@ public function getIdxTable($table = null)
      */
     protected function getStatusExpression(AdapterInterface $connection, $isAggregate = false)
     {
-        $isInStockExpression = $isAggregate ? 'MAX(cisi.is_in_stock)' : 'cisi.is_in_stock';
-        if ($this->_isManageStock()) {
-            $statusExpr = $connection->getCheckSql(
-                'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0',
-                1,
-                $isInStockExpression
-            );
-        } else {
-            $statusExpr = $connection->getCheckSql(
-                'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1',
-                $isInStockExpression,
-                1
-            );
-        }
-        return $statusExpr;
+        return $this->getStatusExpression->execute($this->getTypeId(), $connection, $isAggregate);
     }
 
     /**
diff --git a/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/GetStatusExpression.php b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/GetStatusExpression.php
new file mode 100644
index 000000000000..0b7ee4f578ae
--- /dev/null
+++ b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/GetStatusExpression.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock;
+
+use InvalidArgumentException;
+use Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\ExpressionInterface;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Zend_Db_Expr;
+
+class GetStatusExpression
+{
+    /**
+     * @var array
+     */
+    private $statusExpressions;
+
+    /**
+     * @param array $statusExpressions
+     */
+    public function __construct(array $statusExpressions = [])
+    {
+        foreach ($statusExpressions as $expression) {
+            if (!($expression instanceof ExpressionInterface)) {
+                throw new InvalidArgumentException(
+                    'Expressions must implement '
+                    .'\Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\ExpressionInterface'
+                    .' interface'
+                );
+            }
+        }
+        $this->statusExpressions = $statusExpressions;
+    }
+
+    /**
+     * Returns stock status expression for MySQL query.
+     *
+     * @param string $productType
+     * @param AdapterInterface $connection
+     * @param bool $isAggregate
+     * @return Zend_Db_Expr|null
+     */
+    public function execute(string $productType, AdapterInterface $connection, bool $isAggregate): ?Zend_Db_Expr
+    {
+        $expression = $this->statusExpressions[$productType] ?? $this->statusExpressions['default'];
+        return $expression->getExpression($connection, $isAggregate);
+    }
+}
diff --git a/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/DefaultExpression.php b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/DefaultExpression.php
new file mode 100644
index 000000000000..a7e97f7b6d6e
--- /dev/null
+++ b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/DefaultExpression.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression;
+
+use Magento\CatalogInventory\Model\Configuration;
+use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Store\Model\ScopeInterface;
+use Zend_Db_Expr;
+
+class DefaultExpression implements ExpressionInterface
+{
+    /**
+     * @var ScopeConfigInterface
+     */
+    private $scopeConfig;
+
+    /**
+     * @param ScopeConfigInterface $scopeConfig
+     */
+    public function __construct(ScopeConfigInterface $scopeConfig)
+    {
+        $this->scopeConfig = $scopeConfig;
+    }
+
+    /**
+     * Returns status expressions for MySQL query
+     *
+     * @ingeritdoc
+     * @param AdapterInterface $connection
+     * @param bool $isAggregate
+     * @return Zend_Db_Expr
+     */
+    public function getExpression(AdapterInterface $connection, bool $isAggregate): Zend_Db_Expr
+    {
+        $isManageStock = $this->scopeConfig->isSetFlag(
+            Configuration::XML_PATH_MANAGE_STOCK,
+            ScopeInterface::SCOPE_STORE
+        );
+
+        $isInStockExpression = $isAggregate ? 'MAX(cisi.is_in_stock)' : 'cisi.is_in_stock';
+        if ($isManageStock) {
+            $statusExpr = $connection->getCheckSql(
+                'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 0',
+                1,
+                $isInStockExpression
+            );
+        } else {
+            $statusExpr = $connection->getCheckSql(
+                'cisi.use_config_manage_stock = 0 AND cisi.manage_stock = 1',
+                $isInStockExpression,
+                1
+            );
+        }
+        return $statusExpr;
+    }
+}
diff --git a/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/ExpressionInterface.php b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/ExpressionInterface.php
new file mode 100644
index 000000000000..1e2738ff983c
--- /dev/null
+++ b/vendor/magento/module-catalog-inventory/Model/ResourceModel/Indexer/Stock/StatusExpression/ExpressionInterface.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression;
+
+use Magento\Framework\DB\Adapter\AdapterInterface;
+use Zend_Db_Expr;
+
+/**
+ * Interface for composite status expressions for MySQL query.
+ */
+interface ExpressionInterface
+{
+    /**
+     * Returns status expressions for MySQL query
+     *
+     * @param AdapterInterface $connection
+     * @param bool $isAggregate
+     * @return Zend_Db_Expr
+     */
+    public function getExpression(AdapterInterface $connection, bool $isAggregate): Zend_Db_Expr;
+}
diff --git a/vendor/magento/module-catalog-inventory/etc/di.xml b/vendor/magento/module-catalog-inventory/etc/di.xml
index d2807249cf57..4de38b29402b 100644
--- a/vendor/magento/module-catalog-inventory/etc/di.xml
+++ b/vendor/magento/module-catalog-inventory/etc/di.xml
@@ -133,4 +133,11 @@
     <type name="Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save">
         <plugin name="massAction" type="Magento\CatalogInventory\Plugin\MassUpdateProductAttribute" />
     </type>
+    <type name="Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\GetStatusExpression">
+        <arguments>
+            <argument name="statusExpressions" xsi:type="array">
+                <item name="default" xsi:type="object">Magento\CatalogInventory\Model\ResourceModel\Indexer\Stock\StatusExpression\DefaultExpression</item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/vendor/magento/module-configurable-product/Model/Inventory/ChangeParentStockStatus.php b/vendor/magento/module-configurable-product/Model/Inventory/ChangeParentStockStatus.php
index 9bb4659b31db..4ad15ea905f0 100644
--- a/vendor/magento/module-configurable-product/Model/Inventory/ChangeParentStockStatus.php
+++ b/vendor/magento/module-configurable-product/Model/Inventory/ChangeParentStockStatus.php
@@ -106,6 +106,7 @@ private function processStockForParent(int $productId): void
         if ($this->isNeedToUpdateParent($parentStockItem, $childrenIsInStock)) {
             $parentStockItem->setIsInStock($childrenIsInStock);
             $parentStockItem->setStockStatusChangedAuto(1);
+            $parentStockItem->setStockStatusChangedAutomaticallyFlag(true);
             $this->stockItemRepository->save($parentStockItem);
         }
     }
diff --git a/vendor/magento/module-configurable-product/Model/Plugin/UpdateStockChangedAuto.php b/vendor/magento/module-configurable-product/Model/Plugin/UpdateStockChangedAuto.php
new file mode 100644
index 000000000000..c5a0cd5eae7f
--- /dev/null
+++ b/vendor/magento/module-configurable-product/Model/Plugin/UpdateStockChangedAuto.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+declare (strict_types=1);
+namespace Magento\ConfigurableProduct\Model\Plugin;
+
+use Magento\Catalog\Model\ResourceModel\GetProductTypeById;
+use Magento\CatalogInventory\Model\ResourceModel\Stock\Item as ItemResourceModel;
+use Magento\Framework\Model\AbstractModel as StockItem;
+use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
+
+/**
+ * Updates stock_status_changed_auto setting for configurable product when it was saved manually
+ */
+class UpdateStockChangedAuto
+{
+    /**
+     * @var GetProductTypeById
+     */
+    private $getProductTypeById;
+
+    /**
+     * @param GetProductTypeById $getProductTypeById
+     */
+    public function __construct(GetProductTypeById $getProductTypeById)
+    {
+        $this->getProductTypeById = $getProductTypeById;
+    }
+
+    /**
+     * Updates stock_status_changed_auto for configurable product
+     *
+     * @param ItemResourceModel $subject
+     * @param StockItem $stockItem
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function beforeSave(ItemResourceModel $subject, StockItem $stockItem): void
+    {
+        if (!$stockItem->getIsInStock() &&
+            !$stockItem->hasStockStatusChangedAutomaticallyFlag() &&
+            $this->getProductTypeById->execute($stockItem->getProductId()) == Configurable::TYPE_CODE
+        ) {
+            $stockItem->setStockStatusChangedAuto(0);
+        }
+    }
+}
diff --git a/vendor/magento/module-configurable-product/etc/di.xml b/vendor/magento/module-configurable-product/etc/di.xml
index 01edbe6cd75c..b0d5ff3c6cba 100644
--- a/vendor/magento/module-configurable-product/etc/di.xml
+++ b/vendor/magento/module-configurable-product/etc/di.xml
@@ -272,4 +272,7 @@
             <argument name="serializer" xsi:type="object">Magento\Framework\Serialize\Serializer\Json</argument>
         </arguments>
     </type>
+    <type name="Magento\CatalogInventory\Model\ResourceModel\Stock\Item">
+        <plugin name="updateStockChangedAuto" type="Magento\ConfigurableProduct\Model\Plugin\UpdateStockChangedAuto" />
+    </type>
 </config>
