You shipped a side project on a free tier. It worked on Friday. On Monday it felt slow.
You have no support ticket to open. No status page you trust. No SLA to point at.
So what do you actually have? You have a stopwatch and a shell. That is enough.
Below are five claims developers repeat about free hosting and free model access. Each one fails the same way: it describes a policy instead of a measurement.
Myth 1: "The free tier sleeps, so slow responses are expected"
Maybe it sleeps. Maybe it does not. Why would you guess?
Sleep policy is a property of one deployment at one moment. Providers change it. Plans change. Your traffic changes.
The corrected model is simpler. Treat wake-up cost as an unknown you sample, not a fact you assume.
And write the number down. An assumption you never recorded cannot be debugged.
Myth 2: "A 200 from /health means the service is warm"
A shallow endpoint proves the router answered. That is all it proves.
It says nothing about your database, your cache, or your model call. A process can return 200 while every dependency is cold.
Try this. Split your checks into two depths:
- Shallow check — process is up, returns 200, cheap enough to call every 30 seconds.
- Deep check — touches one dependency and one model call, cheap enough to call every 10 minutes.
Log which depth answered. "Up" and "usable" are different words for a reason.
Myth 3: "One slow request means the platform is slow"
No. It means you did not record whether that request was first or five-hundredth.
Cold start, steady state, and degraded state are three different populations. Averaging them together gives you a number that describes nothing.
So separate them. Run a burst. Then idle. Then hit it once more, alone.
The two-phase probe
This script samples one URL and writes a JSON receipt. Bash 4+, curl, jq.
#!/usr/bin/env bash
# probe.sh <url> [samples] — writes receipt.json
set -euo pipefail
URL="${1:?usage: probe.sh <url> [samples]}"
N="${2:-20}"
OUT="${OUT:-receipt.json}"
PHASE="${PHASE:-burst}"
samples="[]"
for i in $(seq 1 "$N"); do
line=$(curl -sS -o /dev/null \
-w '%{http_code} %{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}' \
--max-time 30 "$URL" 2>/dev/null || echo "000 0 0 0 0 30")
samples=$(jq --argjson i "$i" --arg l "$line" '
($l | split(" ") | map(tonumber)) as $v
| . + [{i: $i, status: $v[0], dns: $v[1], connect: $v[2],
tls: $v[3], ttfb: $v[4], total: $v[5]}]
' <<<"$samples")
done
jq -n --arg url "$URL" --arg phase "$PHASE" --argjson s "$samples" '{
url: $url,
phase: $phase,
probed_at: (now | todate),
n: ($s | length),
ok_rate: ([$s[] | select(.status >= 200 and .status < 400)] | length) / ($s | length),
ttfb_p50: ([$s[].ttfb] | sort | .[length / 2 | floor]),
ttfb_max: ([$s[].ttfb] | max),
samples: $s
}' > "$OUT"
echo "wrote $OUT ($PHASE, n=$N)"
Run it twice. The flags are the whole trick.
PHASE=burst OUT=burst.json ./probe.sh "$URL" 20
sleep 600
PHASE=first-hit OUT=first.json ./probe.sh "$URL" 1
jq -r '.phase + " p50=" + (.ttfb_p50|tostring) + " max=" + (.ttfb_max|tostring)' \
burst.json first.json
The burst run measures steady state. The single sample after idle measures what a returning user pays. Keep both files in the repo.
Mine are my numbers. Yours will differ. Never paste mine into your README.
Myth 4: "Free model access is repeatable, so a red test is my bug"
This one costs people whole afternoons.
A model call is a network call plus a sampler. Both can change under you. A failing assertion may be your code, or it may be today's endpoint.
So isolate the variable. Record what answered, not just that something answered.
- Store the endpoint identifier and the request body hash in each test run.
- Re-run the same prompt three times before debugging your logic.
- Diff the receipt files. If inputs moved, you have a drift problem, not a code problem.
The deep health check is where free model access earns its place. It lets you exercise a real model call on a schedule without budgeting for it. MonkeyCode's free model access and free server option are enough to run this loop end to end — provided you check the current terms yourself.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Myth 5: "It runs on my machine, so the config is portable"
Portability is not a vibe. It is a checklist you either ran or did not.
Before you trust a free environment with a demo, verify these by hand:
- Environment variables — every key the app reads exists there, with the right types.
- Egress — outbound calls to your model endpoint and database actually resolve.
- Secrets — no key is baked into a build artifact or a client bundle.
- Timeouts — your client timeout is shorter than the platform's idle cutoff, or you will chase ghosts.
- Persistence — you know which files survive a restart and which do not.
Any unchecked box is a future incident with a friendly face.
The decision table I actually use
| Workload | Free tier suitable? | Guard before you rely on it |
|---|---|---|
| Portfolio demo, low traffic | Usually yes | Keep the two-phase receipt in CI |
| Internal tool for a small team | Sometimes | Alert on ok_rate drop, not on one slow call |
| Nightly build runner | Sometimes | Measure the first hit after idle first |
| Latency-sensitive API for paying users | No | Buy a contract with an SLA you can read |
| Anything holding regulated data | No | Check terms and data classification first |
That last two rows matter. A free tier is a gift, not a guarantee.
Limitations, and who should skip this
This probe measures one URL from one vantage point. It does not prove global availability.
It cannot see your provider's internal queueing. It will not predict a plan change next month.
Skip this approach if you already have an SLA with credits attached. Skip it if your team has real observability tooling — use that instead.
Also skip it if you will not read the receipts. An unread JSON file is just clutter with good intentions.
What you should take away
Stop arguing about whether the free tier is fast. Start recording what it did, when, and in which state.
Five myths, one fix: measure, label the phase, keep the artifact.
Wondering what your first-hit number actually is? Run the probe tonight. Then you can argue with data instead of folklore.
Top comments (0)