and Cache Warmup Together
The symlink switch is only the beginning. Search index reindex, queue consumer restart and cache warmup are the three hidden waiting periods after every Magento deployment, and they need to be coordinated within the pipeline.
Table of Contents
- 1. The three hidden sources of downtime after a deploy
- 2. Search index: why an immediate reindex is not always necessary
- 3. Adding a controlled reindex to the pipeline
- 4. Queue consumers: pause, drain and a safe restart
- 5. Managing queue consumers in the GitLab pipeline
- 6. Cache warmup: a strategy for the most important pages
- 7. Automating cache warmup in the verify stage
- 8. Timing: the order of post-deploy steps
- 9. Coordinated vs. uncoordinated: a direct comparison
- 10. Summary
- 11. FAQ
1. The Three Hidden Sources of Downtime After a Deploy
The symlink switch in Magento deployments is atomic and takes milliseconds. Anyone who assumes the deployment is finished at that point overlooks three layers that make the difference between a good user experience and visible degradation. The first layer is the search index: after a deployment with schema changes in OpenSearch or Elasticsearch, the index has to be rebuilt. Until that is complete, search results can be incomplete or inaccurate.
The second layer is the queue consumers. Magento uses message queues through RabbitMQ or the MySQL based fallback implementation for asynchronous processing: order confirmations, indexer updates, newsletter dispatch, price calculations. Queue consumers that are running during the deployment keep working with the old code. After the symlink switch they need to be restarted so they pick up the new code. Without a controlled restart, queue consumers can keep running on the old code for minutes or even hours, or crash outright if the old code is incompatible with the new database schema.
The third layer is cache warmup. After a cache flush, Magento responds more slowly to the first requests because every cache is cold. Under heavy load this can cause noticeable latency spikes that show up in monitoring systems as an incident, even though the deployment itself was flawless. A coordinated cache warmup after the deployment prevents these latency spikes by requesting and caching the important pages ahead of time.
2. Search Index: Why an Immediate Reindex Is Not Always Necessary
Not every reindex has to run immediately after a deployment. Magento distinguishes between several indexer types with different impacts. Reindexing the product catalog is often time consuming: for large catalogs it can take hours. If the deployment does not include any changes to the catalog schema or the search configuration, a full reindex is not necessary.
The important distinction: partial indexer updates (indexer:reindex catalogsearch_fulltext) are usually much faster than a full reindex of every indexer. For deployments without schema changes it is enough to let the indexers run in Update by Schedule mode, which processes changes asynchronously. The decision about which indexers need to be rebuilt after which deployment should be documented in the deployment process rather than decided ad hoc.
3. Adding a Controlled Reindex to the Pipeline
A reindex job in the GitLab pipeline ideally runs as an asynchronous step after the symlink switch but before the verify job. It should be controlled through a variable that can be set per deployment. That way, releases without schema changes can skip the reindex job while releases with Elasticsearch mapping changes trigger it automatically.
# Controlled search index rebuild after deployment
reindex:search:
stage: verify
variables:
# Set FORCE_REINDEX=1 for deployments with catalog schema changes
FORCE_REINDEX: "0"
script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- |
if [ "$FORCE_REINDEX" = "1" ]; then
ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
set -euo pipefail
cd "$DEPLOY_PATH/current"
# Rebuild only the search index, not all indexers
bin/magento indexer:reindex catalogsearch_fulltext
echo "Search index rebuild complete"
# Verify index status
bin/magento indexer:status catalogsearch_fulltext
SSH
else
echo "FORCE_REINDEX not set, skipping full reindex"
echo "Invalidating search cache only"
ssh "$DEPLOY_USER@$DEPLOY_HOST" \
"cd $DEPLOY_PATH/current && bin/magento cache:clean full_page"
fi
needs:
- deploy:production
when: on_success
only:
- tags
4. Queue Consumers: Pause, Drain and a Safe Restart
Queue consumers need to be handled deliberately during a deployment. The naive approach, simply letting them keep running, means that after the symlink switch consumers work against the new current directory while PHP processes that were already started still access the old code. This is especially critical for deployments with database migrations: an old queue consumer can try to write data based on the old schema state that the new schema does not expect.
The safe pattern: stop or pause the queue consumers before the symlink switch (bin/magento queue:consumers:stop) and restart them after the switch. The drain step makes sure that all messages currently being processed finish before the consumers are stopped, which avoids lost messages. In RabbitMQ based setups the queue can keep receiving messages while the consumers are stopped; they get processed once the consumers restart, which creates queue lag but no lost messages.
5. Managing Queue Consumers in the GitLab Pipeline
Controlling the queue consumers belongs in the deploy job, not in a manual operations runbook. A deploy job that does not handle queue consumers is incomplete for deployments that include database migrations. The following YAML block shows the safe pattern for managing queue consumers as part of the deployment.
# Queue consumer management integrated into the deploy job
deploy:production:
stage: deploy
script:
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- RELEASE_ID=$(date +%Y%m%d-%H%M%S)
- RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
# Transfer artifact to new release directory
- ssh "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p $RELEASE_PATH"
- rsync -az --delete ./ "$DEPLOY_USER@$DEPLOY_HOST:$RELEASE_PATH/"
- |
ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
set -euo pipefail
# Stop queue consumers before symlink switch (prevents old-code processing)
# This command requires Magento 2.4+ with queue:consumers:stop support
cd "$DEPLOY_PATH/current"
bin/magento queue:consumers:stop --wait-for-running-processes || true
# Link shared resources and switch symlink atomically
RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
ln -sfn "$DEPLOY_PATH/shared/app/etc/env.php" "$RELEASE_PATH/app/etc/env.php"
ln -sfn "$DEPLOY_PATH/shared/pub/media" "$RELEASE_PATH/pub/media"
ln -sfn "$RELEASE_PATH" "$DEPLOY_PATH/current"
# Post-switch: flush cache and restart consumers with new code
cd "$DEPLOY_PATH/current"
bin/magento cache:flush
# Restart queue consumers: systemd or supervisor depending on setup
systemctl restart magento-queue-consumers || supervisorctl restart magento:*
SSH
when: manual
only:
- tags
6. Cache Warmup: A Strategy for the Most Important Pages
A cache flush without a subsequent warmup leaves a Magento system with a completely cold cache. The first requests after the deployment hit unconditioned PHP processes that have to rebuild every cache: block cache, layout cache, config cache, full page cache. For a mid sized shop this state typically lasts several minutes. During that time, page load times are noticeably higher and can cause users to abandon the site.
The warmup strategy prioritizes pages by importance: the homepage, the most important category pages, the most visited product pages. A simple warmup script requests these pages with curl, forcing the caches to be generated. More advanced implementations use Magento native tools such as bin/magento cache:warm or external cache warming services such as Varnish warming scripts. The warmup should run in the verify stage after the deploy job, once the health check confirms that the new release is responding.
7. Automating Cache Warmup in the Verify Stage
Cache warmup in the GitLab pipeline is a verify stage job that requests the most important URLs after a successful deployment. The URL list should be managed as a variable or as a file in the repository so it can be updated easily whenever the shop's page structure changes. A warmup job that hits the wrong pages is useless; one that hits the right pages measurably reduces post deployment latency.
# Cache warmup job: runs after successful deployment verification
warmup:cache:
stage: verify
variables:
SHOP_BASE_URL: "https://shop.mironsoft.de"
WARMUP_TIMEOUT: "30"
script:
# Health check first: only warm cache if the site responds
- curl -f --max-time 10 "$SHOP_BASE_URL/health" || exit 1
# Warm the most important pages sequentially
- |
PAGES=(
"/"
"/sale.html"
"/men.html"
"/women.html"
"/new-arrivals.html"
"/customer/account/login"
"/checkout/cart"
)
for page in "${PAGES[@]}"; do
echo "Warming: $SHOP_BASE_URL$page"
curl -s -o /dev/null -w "%{http_code} %{time_total}s" \
--max-time "$WARMUP_TIMEOUT" \
-H "X-Cache-Warmup: 1" \
"$SHOP_BASE_URL$page" || true
echo ""
done
# Verify full page cache is now active
- |
CACHE_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
--max-time 10 "$SHOP_BASE_URL/")
echo "Homepage status after warmup: $CACHE_STATUS"
[ "$CACHE_STATUS" = "200" ] || exit 1
needs:
- deploy:production
when: on_success
only:
- tags
8. Timing: The Order of Post-Deploy Steps
The order of the post deploy steps is not arbitrary. Queue consumers have to be stopped before the symlink switch so they do not process old messages with the new code or new messages with the old code. The symlink switch itself is the atomic core of the deployment. Immediately afterward comes the cache flush, which clears every Magento cache. Then the queue consumers restart with the new code. Only once the consumers are running and the health check is green can the cache warmup begin.
The reindex should run after the cache warmup and after the queue consumer restart, because it is I/O intensive and should not compete with the warmup traffic. Depending on catalog size, a full reindex can take anywhere from minutes to hours, so it should be scheduled outside peak hours or as a separate, manually triggered job. A clear order for these steps is the difference between a coordinated and an improvised post deploy process.
9. Coordinated vs. Uncoordinated: A Direct Comparison
The difference between a coordinated and an uncoordinated post deploy process does not show up immediately, but in the hours after a deployment. Uncoordinated processes leave visible gaps: search results show outdated data, queue consumers process messages with the wrong code, and users notice clearly longer load times. Coordinated processes close these gaps systematically.
| Post-Deploy Aspect | Uncoordinated | Coordinated (GitLab Pipeline) | Impact |
|---|---|---|---|
| Search Index | Manual or forgotten | Pipeline job with a variable | Clean search results from minute one |
| Queue Consumers | Keep running on old code | Stopped before switch, started after | No schema incompatibilities |
| Cache Warmup | Users warm the cache themselves | Automatic after verify | No latency spikes after deploy |
| Reindex Timing | Simultaneous with warmup | After warmup, outside peak hours | Lower server load |
| Error Diagnosis | No log structure | Pipeline logs per step | Fast root cause analysis |
The investment required for coordinated post deploy steps is manageable. The three jobs, reindex, queue consumer restart and cache warmup, can be integrated into an existing pipeline within a few hours. The savings in avoided incidents, shorter latency spikes and faster error diagnosis outweigh the effort from the very first production use.
10. Summary
Bringing search index, queue lag and cache warmup together for zero downtime means thinking about the deployment process beyond the symlink switch. The switch itself is the fastest step; the three post deploy layers are the real challenge. Search index reindexing has to be a deliberate decision for every deployment: not always necessary, but coordinated whenever it is. Queue consumers must be stopped before the switch and restarted with the new code afterward. Cache warmup prevents latency spikes after the deploy and protects the user experience in the first minutes after the release.
In the GitLab pipeline, these three steps are implemented as jobs in the verify stage that run after the successful deploy job. Each job can be configured, observed and debugged individually. That is the difference between a deployment process that ends at the symlink switch and one that is only complete once the shop responds fully and performs well.
Zero Downtime: Search Index, Queue and Cache, the Essentials at a Glance
Search Index
Not necessary after every deploy. The FORCE_REINDEX variable controls whether catalogsearch_fulltext gets rebuilt.
Queue Consumers
Stop before the symlink switch, restart afterward. Prevents schema incompatibilities during database migrations.
Cache Warmup
Request the most important pages ahead of time after the verify health check. Prevents latency spikes in the first minutes after the deploy.
Order
Stop consumers → symlink switch → cache flush → start consumers → health check → warmup → reindex (if needed).