Most model benchmarks tell you how smart the model is on the first attempt, which is almost never the problem in production. The real problem is what happens on the 120th attempt, when the same kind of input shows up again and nobody is watching. I spent 48 hours running the same classification task against a free model on a free server, and the drift taught me more than accuracy ever did.
The Setup I’d Run Again
The workload was dull on purpose: ten support tickets, three labels, one prompt template. Every hour the job asked the model to classify one ticket and logged the raw output, so each ticket appeared about twelve times. It was not a benchmark of intelligence; it was a probe of stability, and stability is what automation actually needs.
I ran the whole thing on MonkeyCode’s free server option, using the free model access for inference, because a cheap long-running job is exactly the scenario that setup is for. Disclosure: This article was prepared as part of MonkeyCode’s product outreach. The rest is about what the probe caught, not about quotas or latency, so treat my numbers as one operator’s field notes.
The Probe Code (Steal This)
A probe is only honest if it writes down everything, including the outputs you didn’t ask for. The script below hashes every response, tries to parse a label, and appends one JSON line per run, so nothing interesting ever gets lost.
import hashlib, json, time
LOG_PATH = "drift.jsonl"
LABELS = ("bug", "feature", "question")
def stable_hash(text):
return hashlib.sha256(text.strip().encode()).hexdigest()[:12]
def parse_label(raw):
# Accepts JSON or plain prose; returns None when the format is unknown.
try:
return json.loads(raw).get("label")
except json.JSONDecodeError:
found = [label for label in LABELS if label in raw]
return found[0] if found else None
def record_run(run_id, ticket_id, raw, expected):
entry = {
"run": run_id, "ticket": ticket_id,
"hash": stable_hash(raw),
"parsed": parse_label(raw),
"expected": expected,
"ts": time.time(),
}
with open(LOG_PATH, "a") as log:
log.write(json.dumps(entry) + "n")
return entry
The call_model helper is intentionally missing, because the point is the logging discipline and not any particular endpoint. Paste in whatever client you use, wire the function to a scheduler, and let it run for a day before you trust your own automation. The hash column is the part everyone skips, and it is also the part that made the whole experiment worth it.
What Broke, In Order
The Model Started Trusting Its Own Old Answers
About 22 hours in, I noticed a ticket flip to the wrong label and stay there for three consecutive probes. Because my prompt appended the last three answers as a lightweight memory, the model started agreeing with its own output instead of reading the ticket. That is the same failure mode everyone warns about with long context windows: a model that remembers everything eventually trusts all of it, including the parts that are stale. The fix was not smarter prompting; it was deleting the memory and injecting timestamped ground truth instead.
The Parser Was Hiding Format Drift
On run 47 the model wrapped the JSON in a friendly explanation, and my lenient parser still found the right label, so the run looked green. Nothing crashed, but the log recorded a hash that matched nothing else, and that mismatch became the first drift signal I chased. Assume your parser is lying to you, and count malformed responses explicitly, because zero malformed usually means your fallback logic is doing heroic work behind your back.
The Server Dozed Off Twice
The free server dropped my session during two quiet overnight windows, and the retry logic recovered both times without heroics. The in-memory history died with the session, which fixed my stale-echo problem and made the probe count uneven in the table below. I would not call the sleep a bug; I would call it a scheduling constraint that your state file has to survive.
The 48-Hour Numbers
| Window | Runs | Valid JSON | Matched expected | Echoed stale label |
|---|---|---|---|---|
| 0-12h | 30 | 30 | 29 | 0 |
| 12-24h | 30 | 28 | 28 | 4 |
| 24-36h | 30 | 25 | 23 | 7 |
| 36-48h | 30 | 29 | 26 | 5 |
Read the format column, not the accuracy column, because format is what you notice first when something breaks. Accuracy stayed above 80 percent in every window, which sounds fine until you schedule the job and walk away. The echo column is the tell: once my memory hack polluted the context, the wrong label kept reproducing itself.
What I’d Repeat
- Baseline every run against a small reference set with known answers, because the tripwire catches regressions the moment they appear.
- Log the raw output and its hash, even when the parse succeeds, because the hash turns a quiet drift into a searchable pattern.
- Keep history out of the prompt, and inject timestamped ground truth instead, because the model’s memory is a liability, not a feature.
- Treat the server’s sleep as a feature, and make your state file the only thing that needs to survive a restart.
Limitations and Who Should Skip This
This is one workload on one setup in one 48-hour window, which is a decent stability probe and a terrible statistical claim. My experience with the free model access and the free server option was fine, but check current availability yourself before betting a production job on it. Skip this pattern for anything where a mislabel costs money, breaks safety, or triggers compliance, because drift is real even when it is rare.
If your pipeline already has an SLA, a human reviewer, or an audit trail, keep those safeguards; a free tier complements them rather than replacing them. And if your job needs a guarantee about uptime or latency, this approach was never meant for you. The probe is a diagnostic, not a contract.
The Closing
If you run any repetitive model job, steal this probe and let it run for 48 hours before you trust the automation. The accuracy number will look fine, the hashes will start diverging, and you will learn exactly where your own assumptions are hiding. After this experiment, the drift log is the first thing I wire up, and it is a better alarm than any uptime dashboard I have ever maintained.