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.
| Item | Parcel's intended value | What to compare |
|---|---|---|
| Listening address | 0.0.0.0 | App accepts connections beyond loopback |
| Server port | 8080 | App Runner uses the same port |
| HTTP check path | /health | Built image includes this GET route |
| Route behavior | Quick success response | No redirect, login challenge, or long wait |
| Required settings | Available to the new process | Names 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.