AWS
Reliability

Debugging Failed Deployment Health Checks on AWS

Fix an App Runner health check failure by checking the exact image, startup output, listening address, port, and HTTP route.

Forte TeamPublished April 23, 2026Updated November 8, 20266 min read

Your team deploys a Node order API to AWS App Runner using container images built by CodeBuild and stored in ECR. When you release a new commit, CodeBuild packages the image and App Runner pulls it, but the update fails its health check. Rebuilding the same commit leads to the same result.

Look at what happened when App Runner started that exact image. The app needs to stay up and listen on the configured port, and an HTTP check also needs a successful response from the configured route. Startup output helps you see how far the app got. Use the failed image for your checks, because a local checkout may have different files, packages, or settings.

Save the failed release before changing it

For the failed release of our example API, Parcel, the engineer saves the AWS account, Region, App Runner service ARN, time of the update, and image digest. Those details show which image AWS tried to run and where. The engineer also records the previous working release for comparison.

Open the failed App Runner operation and follow its deployment logs. Then inspect application output around the same time. App Runner separates service lifecycle logs from application output in CloudWatch Logs. App Runner log sources

Look for the startup message that tells you Parcel began listening. If the process exited first, save the exception and exit details. A message about missing database configuration points to startup, before the app could answer any health request.

Compare the live settings with the server

App Runner defaults to TCP health checks and also supports HTTP checks. Read the current configuration in case it changed since the last release. If it uses HTTP, check the path, how long App Runner waits for a response, and how many passes or failures change the service's health status. App Runner health configuration

For Parcel, the team builds a comparison sheet. The values below describe its intended setup, rather than universal Node defaults.

ItemParcel's intended valueWhat to compare
Listening address0.0.0.0App accepts connections beyond loopback
Server port8080App Runner uses the same port
HTTP check path/healthBuilt image includes this GET route
Route behaviorQuick success responseNo redirect, login challenge, or long wait
Required settingsAvailable to the new processNames match what the app reads

A server bound only to localhost may answer a request from inside its container while refusing traffic through the container's network interface. A successful local request must therefore be read alongside the listening address and published port.

Check the start command and app setting that select the listening port. The Dockerfile's EXPOSE line describes a port, while the server configuration determines where the app actually listens. Compare that port with the one set in App Runner.

Run the failed image with safe settings

In a separate test setup, run the image from the failed release. Use test services and the settings needed to start the app. Then send a GET request to the configured HTTP path through the container's exposed interface.

Record the response status and duration, along with the related app output. Avoid printing the whole environment; it may contain credentials. Logging that a required key is missing is enough to guide the next check.

If Parcel returns 404, compare the configured path with the routes in the source commit used for the build. The image can only serve routes that were present when it was built, so check that commit before changing the platform configuration.

If the route sends the probe to sign-in or rejects it, review the app's auth rules for that route. Keep the health response small and safe if it must be reachable without login. Test that the narrow change leaves private routes protected.

Fix startup and dependency faults before extending waits

If Parcel exits while reading configuration, importing a package, or starting the server, fix the startup error first. The timeout governs how long App Runner waits for a response, and Parcel needs to stay running before it can send one.

If the process stays up while /health waits on Postgres, check the database address, credentials, and availability. Give any dependency call a timeout short enough for the probe to finish.

Then ask what taking the instance out of service would accomplish if that dependency failed. Parcel can still save orders when the email provider is down, so making email part of /health could interrupt checkout during an outage that only affects confirmations.

Some apps have a slow startup by design. Measure several safe starts before changing timing settings. Use those results to choose timing values that App Runner allows. Extending every wait to hide an unexplained delay can make later failures take longer to detect.

Check the fix as a deployment and as an app

Make one change with a clear link to the evidence. For example, if Parcel listened on the wrong port, change the setting that caused the mismatch. Save the new commit and image identity.

Deploy the new image and confirm that the App Runner operation succeeds. Then create a synthetic order, read it back, and check that the expected release served the request. That test covers the database path the health route may leave out. Keep the failed and successful operation links together so the next person can see what changed.

Inspect the same settings on Forte

Forte Services also need a working HTTP GET route that returns success. Forte discovers the app's port and health path from the app and records deployment steps on the detail page. If a Dockerfile, runtime, port, or route changes, compare those detected values with the new app. Forte deployment steps

In Edit Service, open Advanced Settings and Health Check Configuration. Reset discovery when the saved port or path no longer fits. Saving starts a new deployment. Routine code changes do not need a reset; detection work is billed differently from a standard build. Forte configuration reset, Forte build scope

Forte includes managed rollout and rollback for failed updates when an earlier healthy revision exists. Your team designs the health route, checks that the app still works after the update, and plans separately for any database changes the release makes.

For a test Service, keep the same comparison sheet used for Parcel on App Runner. Follow the deployment guide, check the detected route, and run the synthetic order test after the update becomes healthy.

Check the route your deployment will use

Try a test Service and compare its detected port and health path with the app. Then test an order after the release is healthy.

Choosing What Your Application Health Check Should Test
Reliability
Deployment

Choosing What Your Application Health Check Should Test

Choose what your health route tests based on what a failed check will do. Keep checks quick and test the full order flow on its own.

6 min read
Finding the Right Deployment Logs on AWS
AWS
Debugging

Finding the Right Deployment Logs on AWS

Find the right AWS deployment logs by following one commit through CodeBuild, ECR, and App Runner to the stage that failed.

6 min read