Skip to content
Back to Blog
LLM Cost Cron Prompt Caching Automation

How to Cut LLM API Cost by Moving Cron Jobs Off Peak Hours

Nur Ikhwan Idris ·

I cut my inference bill without changing the model, the prompts, or the output. Twelve cron jobs moved out of the provider's two peak-price windows. Same work, same quality, lower bill. The whole change was a set of edits to schedule expressions.

This is the cheapest optimisation available to anyone running unattended LLM work, and almost nobody checks for it.


1. Providers charge by the clock

Several inference providers now price by time of day. They publish a discount window, usually covering the hours when their own demand is low, and charge the standard rate the rest of the time.

The gap is not decorative. Off-peak rates can run at a fraction of the peak rate for the same model and the same request. If your workload has no opinion about when it runs, you are paying the higher number for no reason at all.

2. Unattended work does not care what time it is

Look at what your scheduler actually runs. Mine included:

  • A nightly news digest.
  • A content research pass that feeds a publishing pipeline.
  • Several log watchdogs that summarise anomalies.
  • A weekly report builder.
  • A memory reflection job that reviews the day's conversations.

Not one of those has a human waiting on it. They were scheduled at whatever hour I happened to pick when I wrote them, which is to say arbitrarily. Twelve of them landed inside the peak windows.

3. The audit

Start by listing every job that spends tokens, with its schedule in UTC. Provider pricing windows are published in UTC, and your crontab probably is not.

crontab -l | grep -v '^#' | awk 'NF' | sort

Then mark each job with three facts: does a person wait for it, how long does it run, and how many tokens does it spend. Anything with no waiting human and a meaningful token spend is a candidate to move.

4. Move, do not downgrade

The tempting alternative is to switch those jobs to a smaller model. I did that once and regretted it. The digest got worse in ways that were hard to measure and easy to feel, and I ended up rewriting prompts to compensate.

Moving a job in time changes nothing about the output. There is no quality trade to reason about, no prompt to retune, and no regression to catch. It is the rare optimisation with no downside beyond the hour a result lands in your inbox.

Watch two things when you move:

  1. Stagger the start times. Twelve jobs at the same minute will fight each other for CPU and hit provider rate limits together.
  2. Keep dependent jobs in order. If research feeds a build, and the build feeds a publish step, preserve the gaps between them.

5. Stack prompt caching on top

Time-of-day pricing composes with prompt caching, and caching is the larger lever if your jobs share a long system prompt.

A cache hit can cost a small percentage of a cache miss on the same tokens. For a fleet of scheduled jobs that all load the same instructions, that means the shared prefix is nearly free after the first call. The requirement is that the prefix stays byte-identical, so put anything that varies at the end of the prompt.

6. What this does not fix

Be clear about the limits before you celebrate.

  • Interactive work cannot move. A person waiting for an answer sets the clock, not you.
  • A job that runs badly still runs badly, just cheaper. Fix the retry loop first.
  • Providers change pricing. Write the windows in a comment next to the schedule so the next person knows why the times look odd.

The takeaway

Before you change model or trim features, open your crontab and check it against your provider's pricing clock. Work nobody is waiting for should run when the tokens are cheapest. It is an afternoon of edits and it never has to be revisited.