Skip to content

About

The same Node and Express app twice - as an AI tool generates it, and deployable. Four faults reproduced with their real output: a container reporting Up that returns HTTP 000, a start script whose necessity depends on the filename, a key readable from the image, and data that survives a restart but not a deploy.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

deploy-failure-lab

Deploy on Back4app

The same small app twice: once the way an AI tool hands it to you, and once with the four deployment faults removed. A notes API in Node and Express. On a laptop both versions behave identically. In a container only one of them answers.

Measured on 9 October 2026: the generated version reports Up with its port mapped and returns HTTP 000 to every request, because it listens on 127.0.0.1:3000 while the platform passed PORT=8080. compare.sh reproduces that and the three other faults in one run.

Read the article: Why Your App Works Locally and Crashes When You Deploy It

What it does

broken/ and fixed/ hold the same four endpoints. The difference is four lines.

Fault broken/ fixed/
Port app.listen(3000, '127.0.0.1') app.listen(process.env.PORT || 3000, '0.0.0.0')
Start command no start script "start": "node server.js"
API key pasted into the source process.env.OPENAI_API_KEY
Storage a file in the container a managed backend over REST

What we measured

── the app as generated ─────────────────────────────────────────────
  platform status : Up 4 seconds
  a request       : HTTP 000
  listening on    : 127.0.0.1:3000
  PORT offered    : 8080
  key in the image: 1 occurrence(s)

── the same app, fixed ──────────────────────────────────────────────
  a request       : HTTP 200
  listening on    : 0.0.0.0:8080
  key in the image: 0 occurrence(s)

Two findings worth the run:

A missing start script is not always fatal. npm substitutes node server.js when a file of that name exists, so the same package.json with no start script runs in one project and fails with npm error Missing script: "start" in the next. The deciding factor is what the entry file was named.

Data survives a restart and not a deploy. A note written to a file inside the container was still there after docker restart, and gone once the container was replaced from the same image — which is what a deploy does. The obvious test passes, which is why this one costs people so much time.

How we measured: every number comes from compare.sh against Docker 29.4.3 on arm64, with the container run exactly as a platform runs it — PORT in the environment and the port published.

Files

  • broken/ — the app as generated: hardcoded port on the loopback, no start script, key in the source, SQLite file on local disk.
  • fixed/ — the same endpoints with all four corrected.
  • compare.sh — builds both and prints the table above.

Deploy your own

  1. Create a free account. Sign up at https://www.back4app.com/signup?utm_source=github&utm_medium=repo&utm_campaign=deploy-failure-lab.
  2. Backend: create an app, then copy the Application ID and the REST API key from App Settings → Security & Keys. The fixed/ version stores its notes there, so the container keeps no state.
  3. Container: push this repository, then Web Deployment → Deploy from GitHub, with fixed/ as the root directory. Set OPENAI_API_KEY, PARSE_APP_ID and PARSE_REST_KEY as environment variables. Leave the port alone — the app reads it.
  4. Deploy broken/ the same way if you want to watch it fail. It will report healthy.

Run locally

cp .env.example .env      # PORT, OPENAI_API_KEY, PARSE_APP_ID, PARSE_REST_KEY
./compare.sh

compare.sh needs only Docker. The storage half of the comparison needs the two Parse values; without them the fixed app still starts and answers /healthz.

What the platform gives you

Containers build the Dockerfile, pass a port in PORT, hold your environment variables outside the image, and replace the container on every deploy — which is why the fourth fault matters. The managed Parse Server behind it keeps the data that must outlive that replacement, with REST and GraphQL APIs and Cloud Code. Documentation: https://www.back4app.com/docs-containers?utm_source=github&utm_medium=repo&utm_campaign=deploy-failure-lab · https://www.back4app.com/docs?utm_source=github&utm_medium=repo&utm_campaign=deploy-failure-lab.

License

MIT.

About

The same Node and Express app twice - as an AI tool generates it, and deployable. Four faults reproduced with their real output: a container reporting Up that returns HTTP 000, a start script whose necessity depends on the filename, a key readable from the image, and data that survives a restart but not a deploy.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages