← All posts

A stale date.today() broke a long-running Gunicorn service

How startup-time evaluation caused the LLM context and backend validation to disagree after midnight.

Service
Weather Agent
Severity
Minor
Status
Resolved
#Python#Gunicorn#LLM

Summary

A date used as “today” was evaluated while Gunicorn started and then reused for later requests. Once the process crossed midnight, the LLM received stale time context while backend validation used the current date.

Impact

Relative dates could be interpreted against yesterday while the backend checked them against today. Each component behaved consistently with its own input, but the combined request failed.

What happened

The bug appeared only after a worker had remained alive across a date boundary. Restarting the service refreshed the value and temporarily made the problem disappear.

Root cause

A call to date.today() lived in startup or module-level state instead of the request path. The value therefore described when the process started, not when the request arrived.

The failure required several mechanisms to line up:

  • a long-running Gunicorn worker;
  • startup-time evaluation;
  • request-time backend validation;
  • relative-date interpretation in the LLM prompt.

Resolution

Time-dependent context is now evaluated for each request so the prompt and validation layer share the same current date.

What I learned

Values named “current” or “today” need a clearly defined evaluation time. Restarting a process is not a fix when process lifetime is the hidden input.

Follow-up

  • Keep clock reads close to the operation that uses them.
  • Pass one request-scoped date through all relevant layers.
  • Add a test that crosses midnight without restarting the process.