Does JobRunr Remember Between Runs? Jobs Are Stored as JSON in Your Database. The Next Job Still Starts With Only Its Arguments.
Does JobRunr Remember Between Runs? Jobs Are Stored as JSON in Your Database. The Next Job Still Starts With Only Its Arguments. JobRunr remembers jobs in a way most Java schedulers do not. A job is not held in a worker's memory and it is not pushed into a separate broker that the team has to operate. The library inspects the lambda or method reference, serializes the type, the method, and the arguments to JSON, and writes that record into the database the application already uses. That record
Does JobRunr Remember Between Runs? Jobs Are Stored as JSON in Your Database. The Next Job Still Starts With Only Its Arguments.
JobRunr remembers jobs in a way most Java schedulers do not. A job is not held in a worker's memory and it is not pushed into a separate broker that the team has to operate. The library inspects the lambda or method reference, serializes the type, the method, and the arguments to JSON, and writes that record into the database the application already uses. That record survives restarts, deploys, and crashes. It is also easy to misread. When the job runs, the code receives the arguments stored with that record, and almost nothing else. What an earlier job learned is not in the record unless earlier code wrote it somewhere the next job knows to read.
A job is a serialized call, not a continuing conversation
Code calls BackgroundJob.enqueue(), schedule(), or scheduleRecurrently(), or uses an injected JobScheduler. The scheduler inspects the lambda using ASM, captures the target type, method, and arguments, serializes that envelope to JSON, and inserts a Job record through the StorageProvider.
Later, BackgroundJobServer instances poll storage for due jobs, claim a job atomically so only one server processes it, deserialize the payload, and invoke the method. The Job entity names what persists: the name and signature, the JobDetails holding type, method, and arguments, and a history of every state the job passed through. That history records that a job was enqueued, scheduled, processing, succeeded, or failed, and how many times it was retried.
Nothing in that structure accumulates findings. A job that inspects an account, calls a model, and decides the account needs a human review has nowhere in its own record to leave that decision for tomorrow's job. The decision leaves the JVM with the method return unless application code stores it deliberately.
What the StorageProvider actually keeps between runs
Three kinds of things persist, and naming them precisely prevents most confusion.
First, the job definition persists. With a durable provider backed by PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, or MongoDB, enqueued and scheduled jobs stay in storage until a server claims them. The exception proves the rule: the InMemoryStorageProvider used in tests and quick starts loses its jobs when the process restarts, precisely because nothing durable was written.
Second, the delivery bookkeeping persists. States move through enqueued, scheduled, and processing toward succeeded or failed. A failed job is retried automatically by default up to 10 times with exponential back-off, and every attempt is added to the history the dashboard draws, in JobRunr 9 as a timeline chart. Since version 9, results of steps wrapped in JobContext.runStepOnce() also persist with the job, so a retry can skip a completed step and reuse its stored, serializable result.
Third, whatever application code writes for itself persists. A method can update an application table, write a checkpoint keyed by an ID in its arguments, or attach a summary to the next job it enqueues. Those writes are the whole bridge between runs, and every part of that bridge is manual: deciding what to save, where it lives, and teaching the next run where to look.
Recurring jobs make the boundary easiest to see
A recurring job feels like one job that keeps coming back, so its mechanism deserves a close look. A RecurringJob is a Job with a cron expression or a fixed interval attached. The longest-running server, elected as master, checks due recurring jobs on each poll cycle and enqueues a fresh fire-and-forget job for each one that comes due. The open source edition supports up to 100 recurring jobs.
Monday's run and Tuesday's run are siblings, not a continuation. Tuesday's job is a new record, created from the same definition, carrying the arguments that definition produces at that moment. If Monday's run discovered that a customer already replied or a lead already signed, that discovery does not flow into Tuesday's record on its own.
A retry is different: it is the same job continuing its own delivery, which is why attempt counts and runStepOnce() results can guide it. Step results help a retry avoid repeating a charge that already completed inside that job. They do not turn separate jobs, on separate days, into one shared memory.
Where an AI step inside a JobRunr job goes blind
Add a model call inside a scheduled method and the gap stops being abstract. Consider a nightly job that reviews new support conversations, drafts replies, and flags accounts that need attention. On the first night, the method reads the arguments, calls the model, and produces useful judgments: this account was already offered a refund, that conversation was already taken over by a human, this topic was already answered last week in a different tool.
On the second night, a new job record arrives. It carries a date, an account ID, perhaps a batch size. It does not carry last night's judgments, unless last night's code wrote them into a table and tonight's code queries that table before calling the model. Without that hand-built loop, the agent repeats work already done and can contradict a decision another run or tool already made. The scheduler did its job perfectly. Memory was never part of its job.
Give the job a memory it can read before it reasons
The fix is to separate two concerns: scheduling the work, and remembering the work. JobRunr handles the first well, with durable storage, distributed claiming, retries, and a dashboard. The second needs a memory layer that every run, and every tool around the run, can read and write in the same place.
Vilix AI is built for that second concern. Vilix AI is cloud-hosted, so there is zero infrastructure to deploy or manage alongside the application database. The same memory is available everywhere over MCP, so a JobRunr job, a coding assistant, a chat tool, and another scheduled agent can all read from and write to one shared memory instead of keeping private notes. Vilix AI stores full conversation history, not just extracted facts, so the next run can revisit what was actually said and decided, in context, rather than working from a compressed summary.
For a nightly review job, the change in shape is simple. Before the model reasons, the job retrieves relevant memory: prior decisions for that account, earlier conversations, and rules the team settled in other tools. After the job acts, it saves what it did and learned back to the same memory. The next run, in any tool connected to that memory, starts from that record instead of from its arguments alone.
Vilix AI is free forever on the free plan, with a 7-day Pro trial that requires no credit card. Data can be exported or deleted at any time, so adopting a shared memory does not lock the history inside it.
JobRunr will keep remembering what it was designed to remember: a serialized call, its arguments, its state history, and its completed steps. Give the AI steps inside those jobs a memory designed for reasoning, and each run stops starting blind.