# Job (/academy/job)



A [queue](/academy/queue) is the tray. A **job** is one slip.

"Resize upload 88." "Retry Polar invoice 12." "Send the digest for this list." Named. Finite. You can ask whether it ran, whether it succeeded, whether it failed. If you cannot say what done looks like in one sentence, it is not a job yet. It is a vibe.

That split saves you at 3 a.m. The [server](/academy/server) can be healthy while one job, for one user, on one night, died quietly. "Is the app up?" is the wrong question. "Did job `welcome-email:41` finish?" is the right one.

**Why the slip has a name**

* You can retry it. A failed job goes back in the tray. "The server was busy" is not retryable unless you wrote the busy thing down.
* You can schedule it. [Cron](/academy/cron) is just a printer that emits the same slip every Monday.
* You can hand it to a [worker](/academy/worker) that only knows this one errand.

The [CLI](/academy/cli) you already use is full of jobs you did not call jobs. `npx create-hackhaton-space-stack@latest my-app --yes` is one: start, finish, or fail. CI is a hallway of them. Your product should be too, the moment anything happens after the click.

[Agents](/academy/agent) get more stable when you stop asking them to "handle onboarding" and start asking them to enqueue three jobs with ids. Ambiguous wishes do not retry. Slips do.

At a hackathon, name the leftover. Welcome mail. Receipt. Nightly wipe. Each one is a job you can point at when a judge asks why their email never showed. The [API](/academy/api) accepted the click. The slip is how you prove the rest.

**What this unlocks**

Work becomes countable. Countable work can fail in public, get a second chance, and stop living in a teammate's head. The tray holds slips. The worker does one. You sleep if the names are good.

Without jobs you have a busy app. With jobs you have a list.
