Health Endpoint, Smoke Tests, Database Check, Cache Check
A deployment that's considered successful right after the symlink switch hasn't actually concluded on a functional level. Post-deploy checks make the difference between a pipeline that ends technically and a pipeline that confirms the application actually works.
Table of Contents
- 1. Why Post-Deploy Checks Belong in the Pipeline
- 2. Health Endpoint: The First Sign of Life Check
- 3. Smoke Tests: Checking Critical Paths in Seconds
- 4. DB Check: Validating Database Connection and Migration
- 5. Cache Check: Magento Cache Status After Deploy
- 6. Configuring the Verify Job in GitLab CI
- 7. What Should Happen When a Check Fails
- 8. Timeouts and Retry Logic in Verify Jobs
- 9. Check Methods Compared
- 10. Summary
- 11. FAQ
1. Why Post-Deploy Checks Belong in the Pipeline
A deployment doesn't end with the symlink switch or the final cache:flush command. It ends when the application demonstrably responds to requests, the database is reachable, the cache has been correctly initialized, and critical paths like login, checkout, and API routes work. Without post-deploy checks, the pipeline gets stuck on a technical definition of "successful" that says nothing about the actual state of the application.
In practice that means a deploy can run technically flawlessly and still leave behind a broken application. A misconfigured environment variable, an incompatible cache entry from the old release, a failed migration that didn't return a non-zero exit code: all of that stays invisible without a verify stage, until a user or a monitoring system reports the error. Post-deploy checks close this gap before it turns into a problem.
The good news: for Magento deployments the most important checks are simple to implement. A curl -f against the health endpoint, a bin/magento cache:status, a simple DB connection test via the Magento CLI, and an HTTP status check on critical pages: these aren't complex tests, just minimal checks with a high detection value. They take under 30 seconds and belong in every production deploy process.
2. Health Endpoint: The First Sign of Life Check
The health endpoint is the fastest and most robust first check after a deployment. It should return a simple JSON response with HTTP status 200 and deliberately not query the database or warm the cache: it only checks whether the PHP application is reachable and responds at a basic level. In Magento, an endpoint like this can be implemented as a simple controller module that does nothing more than output a static JSON response.
A health endpoint has another advantage: it can be used simultaneously by the load balancer, monitoring systems, and the GitLab pipeline. That means the same endpoint checked by the verify job during deployment can also be monitored continuously during normal operation. A health endpoint, once implemented, pays off in many contexts.
# Verify stage: post-deploy checks for Magento
verify:production:
stage: verify
needs: ["deploy:production"]
script:
# Step 1: Health endpoint, basic PHP reachability
- |
for i in 1 2 3 4 5; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://shop.example.com/health)
if [ "$STATUS" = "200" ]; then
echo "Health check passed (attempt $i)"
break
fi
echo "Health check failed with status $STATUS, retrying in 5s"
sleep 5
[ $i -eq 5 ] && exit 1
done
# Step 2: Homepage smoke test
- curl -f --max-time 15 https://shop.example.com/
# Step 3: Cache status via Magento CLI
- |
ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"cd ${DEPLOY_PATH}/current && php bin/magento cache:status" \
| grep -v "disabled" || { echo "Cache check failed"; exit 1; }
when: on_success
allow_failure: false
3. Smoke Tests: Checking Critical Paths in Seconds
Smoke tests check the application's most important pages and functions at the HTTP level, without logging into the application logic or simulating complex user scenarios. For a Magento store that means: homepage, category page, product detail page, cart page, and if possible the login page. These five pages cover the most critical rendering paths without needing to simulate an actual checkout process.
The central tool for smoke tests in GitLab pipelines is curl with the flags -f (error on non-200 status), --max-time (timeout), and -L (follow redirects). This combination reliably detects 500 errors, maintenance pages, broken redirects, and timeout problems: all typical symptoms of a broken deployment. Anyone who also wants to check the HTTP response headers can work with curl -I and grep.
4. DB Check: Validating Database Connection and Migration
A DB check after deployment ensures that the database connection works from the new release directory and that all migrations were applied correctly. Magento provides a command with bin/magento setup:db:status that checks exactly that: it reports whether there are pending migrations that haven't run yet. A non-zero exit code means the database isn't in the expected state.
This check is especially important because setup:upgrade sometimes ends with exit code 0 in certain error states even though the migration didn't actually complete. That happens rarely, but when it does, the application stays in an inconsistent state until it's manually detected and fixed. A setup:db:status in the verify job catches this case and blocks the pipeline before users experience the broken state.
5. Cache Check: Magento Cache Status After Deploy
After a Magento deployment, the cache check should confirm two things: that all critical cache types are enabled and that no cache entries flagged as invalid point to an incomplete setup step. bin/magento cache:status outputs a tabular overview of all cache types with their current state. A disabled entry for config or layout is a warning sign.
It's also worth checking whether Redis is reachable as the cache backend. A simple redis-cli ping over SSH that returns PONG confirms the connection. If Redis doesn't respond and Magento falls back to file based caching, performance degrades drastically without any explicit error being visible. This check costs one second and prevents silent performance degradation after deployment.
# Extended verify job with DB check and Redis connectivity
verify:extended:
stage: verify
needs: ["deploy:production"]
script:
# Check Magento DB migration status
- |
DB_STATUS=$(ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"cd ${DEPLOY_PATH}/current && php bin/magento setup:db:status 2>&1")
echo "$DB_STATUS"
echo "$DB_STATUS" | grep -q "All modules are up to date" \
|| { echo "DB migration check failed"; exit 1; }
# Check Redis connectivity
- |
REDIS_PING=$(ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"redis-cli -h ${REDIS_HOST} ping 2>&1")
[ "$REDIS_PING" = "PONG" ] \
|| { echo "Redis not reachable: $REDIS_PING"; exit 1; }
# Check all required cache types are enabled
- |
ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"cd ${DEPLOY_PATH}/current && php bin/magento cache:status" \
| grep "disabled" && { echo "Cache types disabled, check needed"; exit 1; } || true
# Verify static files are present
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}" \
"test -f ${DEPLOY_PATH}/current/pub/static/frontend/Mironsoft/default/de_DE/requirejs-config.js" \
|| { echo "Static files missing"; exit 1; }
when: on_success
6. Configuring the Verify Job in GitLab CI
The verify job in GitLab CI is defined as its own stage after the deploy stage. The needs keyword ensures the verify job only starts once the deploy job has completed successfully. With allow_failure: false, a failed verify job marks the entire pipeline as failed, which is the desired behavior, since a failed verify corresponds to a broken deployment.
For environments with a warmup period after the symlink switch, for example when PHP-FPM processes are still holding old opcache entries, the verify job should have an initial delay. That can be achieved with a simple sleep 10 before the first checks. Alternatively, you can implement a retry loop that tries up to five times and breaks on success, which is more robust than a fixed sleep.
7. What Should Happen When a Check Fails
A failed post-deploy check is not an error that can be ignored, it's the signal that the deployment ended in a broken state. The response has to be clearly defined before the first failure occurs. The three most common response patterns: an immediate manual rollback via the GitLab pipeline, an automatic rollback through an on_failure stage, and an immediate alert notification to Slack or email while the rollback decision is made manually.
The automatic rollback pattern sounds appealing but comes with an important caveat: if the verify job fails after a successful DB migration and an automatic rollback runs, the code state points back to the old release while the database structure matches the new version. That can lead to an inconsistent state. For deployments with database migrations, a manually approved rollback is therefore often the safer choice.
8. Timeouts and Retry Logic in Verify Jobs
Verify jobs need to be equipped with timeouts and retry logic, because production systems don't guarantee immediate full availability right after a deployment. PHP-FPM pools can be briefly overloaded, the first request after an opcache clear takes longer than usual requests, and the cache first has to warm up before response behavior normalizes. A verify job that fails immediately on the first timeout produces false negatives.
The recommended strategy: a loop with a maximum of five attempts, a five second wait between attempts, and an explicit exit code 1 after the last failed attempt. That gives the application up to 25 seconds to stabilize without turning the verify job into a permanent hang. With timeout: 3 minutes at the job level, there's also a hard upper limit.
# Smoke test job with proper retry logic and timeouts
verify:smoke:
stage: verify
timeout: 3 minutes
script:
# Allow application to stabilize after symlink switch
- sleep 10
# Retry loop for homepage check
- |
for attempt in 1 2 3 4 5; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
--max-time 10 --connect-timeout 5 \
https://shop.example.com/)
if [ "$HTTP_CODE" = "200" ]; then
echo "Homepage OK (attempt $attempt)"
break
fi
echo "Attempt $attempt failed, HTTP $HTTP_CODE"
[ $attempt -lt 5 ] && sleep 5 || exit 1
done
# Category page check
- curl -f --max-time 15 https://shop.example.com/category-name/
# Product detail page
- curl -f --max-time 15 https://shop.example.com/product-url.html
# Admin login check: should return 200, not 302 to maintenance
- |
ADMIN_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
https://shop.example.com/admin/)
[ "$ADMIN_CODE" = "200" ] || [ "$ADMIN_CODE" = "302" ] \
|| { echo "Admin unreachable, HTTP $ADMIN_CODE"; exit 1; }
when: on_success
9. Check Methods Compared
Not all post-deploy checks are equally valuable. The table below shows the most common methods, their detection depth, and their typical execution time in the verify job.
| Check Method | What It Detects | Runtime | Recommendation |
|---|---|---|---|
| Health Endpoint | PHP reachable, no 5xx | < 1s | Always |
| Homepage curl -f | Rendering, layouts, blocks | 1-5s | Always |
| cache:status | Disabled cache types | < 2s | Always |
| setup:db:status | Pending migrations | 2-5s | On DB changes |
| redis-cli ping | Redis connection | < 1s | When Redis is active |
The combination of health endpoint, homepage smoke test, and cache:status is the minimum standard that should run after every Magento deployment. The DB check and Redis check get added for releases that include database migrations or cache configuration changes. This differentiation allows fast verify jobs for small releases and more thorough checks for larger deployments.
10. Summary
Post-deploy checks are the difference between a pipeline that ends technically and a pipeline that concludes functionally. Health endpoint, smoke tests, DB check, and cache check together cover the most important failure classes after a Magento deployment: PHP unreachable, broken rendering, incomplete migration, disabled cache types, unreachable Redis. These checks run in under 30 seconds and require no external test frameworks.
The most important thing isn't perfect test coverage, it's consistent execution after every deployment. A simple health check and a homepage smoke test that run on every release are worth more than an extensive test suite that occasionally gets skipped due to time pressure. Automation beats completeness when it comes to post-deploy checks.
Post-Deploy Checks: The Essentials at a Glance
Health Endpoint
The simplest check: HTTP 200 from the health endpoint. Confirms PHP reachability without business logic, fast and reliable.
Smoke Tests
curl -f against critical pages (homepage, category, product). Detects rendering errors and 500 responses without a browser.
DB & Cache
setup:db:status checks migrations. cache:status checks disabled cache types. redis-cli ping confirms the cache backend.
Retry Logic
5 attempts, 5 seconds apart. Gives the application time to stabilize without false negatives from opcache warmup.