Skip to content
Scalpels home

Scalpels is officially launching on October 31, 2026. Special early adopter pricing is available now.

← All guides

Guide

A Comprehensive Agent's Guide to Laravel Cloud

Hibernation and idle cost

· Ed Grosvenor

Scale-to-zero only saves money if the application actually goes idle. On most of the applications we looked at, something kept it awake: a bot, a scheduler, a health check, a database session, an open socket. Cloud cannot tell you which. This page is about finding out.

How hibernation behaves

  • It is configured on the application instance. Application instances cannot have a minimum of zero replicas. Scale-to-zero is a separate setting:

    cloud instance:update <app-instance-id> --scale-to-zero=true --scale-to-zero-timeout=5 --force -n
    

    The timeout is in minutes. Older CLIs and API fields call this hibernation, and --hibernation still works as an alias.

  • The process is frozen, not stopped. Nothing restarts and no boot line is logged. In-process state survives, and the monotonic clock does not advance while frozen. One application froze about five minutes and ten seconds after its last request on a five-minute timeout.

  • Waking costs time. We measured 6 to 10 seconds to first byte on the smallest legacy size, and under 2 seconds on the current flex-512mb style sizes. Earlier observations saw 10 to 20 seconds and a 502 while replicas woke. A cold start is the price of sleeping, not a broken deployment.

  • Nothing in the status shows it. A frozen environment still reports running. Read the replica count from cloud environment:metrics (v0.6.3) or GET /api/environments/{id}/metrics.

  • Re-read the settings after every deploy. A redeploy once reset our timeout from five minutes to one, and the flag read back inconsistently right after an update. Editor's Note: That was actually me setting that by hand to see how low a value would be accepted.

What keeps an application awake

Any inbound request resets the timer. So does anything the application does on its own.

  • The scheduler. An application instance with usesScheduler: true runs the scheduler every minute, so it never hibernates. If an application needs both a scheduler and sleep, the scheduler has to live somewhere else.
  • Long-lived connections. An open WebSocket or server-sent events connection keeps it awake for as long as it stays open. We measured one application awake 34.6% of the time purely from a heartbeat, asleep five minutes after the socket closed.
  • Bots and monitors. In one investigation, a single bot requesting / every 3.3 minutes, inside a five-minute window, accounted for 108 of 123 awake minutes. Uptime monitors do the same thing on purpose.
  • Credential scanners. Custom domains attract constant probes for .env, .git/config and the like. We logged 65 such requests in three seconds. Cloud's path blocking stops the obvious ones, but bots hitting real routes such as / and /login still count.
  • Queue polling by a worker with a minimum of one replica.

The database has its own idle timer. Serverless Postgres suspends after it has been idle for its suspend period, five minutes on the clusters we checked. Anything that queries it wakes it, which on a public page usually means:

  • A database session driver, which writes on every guest request. Use cookie sessions, which is Cloud's default.
  • A health check that queries the database. Point monitors at a route that touches neither the session nor the database.
  • Pages that set a cookie or query for every guest, so the edge can never cache them.

Fix the cause in the right order

When telemetry shows what kept an application awake, fix it in this order:

  1. Deal with the traffic itself. Identify the bot, slow it, or point it at a route with no session and no database.
  2. Stop public pages doing work for guests. A page that sets a cookie or queries the database for an anonymous visitor wakes everything. Cache-Control: no-cache, private with Vary: Cookie makes a page uncacheable, so look for those headers on routes that should be cacheable.
  3. Only then add an edge cache. Caching a page that sets a cookie on every response does nothing.

If cost data shows a serverless database whose spend never changes between periods, start here: something wakes it constantly. See Attribute cost.

Find what kept it awake with Hone

Cost data can tell you that a serverless database never slept. It cannot tell you what kept waking it up.

Hone records requests, queries, jobs, scheduled tasks, outgoing HTTP calls and cache activity, using Laravel Nightwatch's instrumentation, and keeps them in your own Cloud organization. Use it to identify the actual activity behind a flat compute line: a scheduler running every minute, a health check that queries the database, a persistent job loop, or requests arriving more often than the scale-to-zero delay.

From v1.5.0 it answers this directly. Its idle-cost tools, available to agents over its MCP server, classify every execution as a human, a guest, a scheduled task, a job or a command, and keep per-minute activity for 400 days:

  • awake_segments shows when an application's compute and database were awake, and which kind of activity kept them so, given the idle timeouts you configure.
  • guest_traffic_clusters groups the anonymous traffic that kept it awake by path, user agent and network.
  • guest_db_routes lists public routes that query the database for guests.
  • background_db_activity lists scheduled and queued work that touches the database, and how often.
  • edge_profile reports, per route, whether responses set cookies and how they are cached.

That evidence lets you fix the cause instead of merely resizing the resource. Hone does not read Cloud's billing or hibernation settings. You give it your idle timeouts, and it tells you what happened against them. Pair it with the cost reconciliation, which tells you where the money went.

Watch the things that grow

Idle cost is not the only quiet cost. Two from our own operations:

  • A maintenance job that failed silently stopped pruning a telemetry table. It grew to 21 GB in 20 days, against a 72-hour retention policy, on a small serverless database whose compute was pinned to the minimum. Nothing alerted for 17 days. Alert on the age of your last successful maintenance run, not just on errors.
  • A dead service still bills. For eight days an ingest endpoint rejected every request after an authentication change, while compute and the database kept serving the rejections. Measure success from the receiving side, by rows written or credentials used, not from status codes on unrelated routes.

Serverless Postgres details that mattered in that investigation: compute is bounded by the cluster's cu_min and cu_max, and cu_max is the whole CPU story. pg_stat_statements is not installed, so use pg_stat_user_tables for per-table activity. DELETE does not return storage until the table is vacuumed or repacked. Point-in-time recovery may be off, so check retention before you rely on it.

Extra resources

https://fastlaravel.com/ - A course by JMac that goes deep on using Cloudflare with Laravel applications.

Want some help?

After you buy, we will pay for an hour with one of these experts to help you get everything up and running.

  • Artisan Build

    USA

    We run Scalpels, as well as a suite of other tools for developers and development teams.

    Agency Ask for help
    Ask Artisan Build for help