Does BullMQ Remember Between Runs? Jobs Are Stored in Redis. The Next Job Still Starts With Only Its Payload.
Does BullMQ Remember Between Runs? Jobs Are Stored in Redis. The Next Job Still Starts With Only Its Payload. BullMQ keeps jobs in Redis, and those records are detailed. A job carries its payload, its state, its progress, its logs, and the value it returned or the error it failed with. None of that record is handed to the next job on the queue. Every new job starts with exactly the data it was added with, and nothing the previous job learned comes along unless code moves it there by hand. Wha
Does BullMQ Remember Between Runs? Jobs Are Stored in Redis. The Next Job Still Starts With Only Its Payload.
BullMQ keeps jobs in Redis, and those records are detailed. A job carries its payload, its state, its progress, its logs, and the value it returned or the error it failed with. None of that record is handed to the next job on the queue. Every new job starts with exactly the data it was added with, and nothing the previous job learned comes along unless code moves it there by hand.
What BullMQ actually keeps
When a producer adds a job, BullMQ serializes the job's data to JSON and stores it in Redis. The job sits there through restarts, crashes, and deploys until a worker claims it, moving through clear states: waiting, delayed, prioritized, active, then completed or failed. A job added before a crash is still there when the worker comes back.
A running job can add to its own record. It can report progress with job.updateProgress(), append lines with job.log(), and finish by returning a value. On failure, BullMQ records the error and stack trace, and retry settings decide whether the job goes back to waiting with a backoff or lands in the failed set. Completed and failed jobs are kept in Redis by default, until retention settings such as removeOnComplete and removeOnFail trim them by age or count.
Scheduling has its own memory too. Repeatable jobs and the newer Job Schedulers store the pattern in Redis, keyed by a scheduler ID, so an upsert with the same ID updates the schedule instead of creating a second one. BullMQ remembers when to fire, reliably, across restarts.
Flows add one narrow channel: a parent job can wait for child jobs and read their return values with getChildrenValues(). That sharing works inside one flow tree only.
So BullMQ keeps four things: each pending job's payload, each finished job's record, its schedulers' patterns, and return values passed inside a single flow. None of them briefs the next independent job.
What the next job starts with
A worker receives a job object whose data field holds only what the producer passed to queue.add(). If a scheduled job fires every morning with the same payload, every morning's job receives the same starting point, whatever yesterday's job discovered, decided, or promised.
Yesterday's completed record does not change that. It sits in Redis under yesterday's job ID, holding a return value and logs. Today's job does not look it up, does not search past jobs for relevant history, and does not merge anything into its own briefing. Code you write has to do every one of those steps: know which job IDs matter, read them before retention trims them, and turn stored return values back into usable context.
The scheduler's memory is thinner still. Knowing that a scheduler fired at 7 a.m. proves the schedule ran. It says nothing about what the job found, what a customer replied, or which follow-up is now due.
Picture a scheduled job that reviews new support requests each morning and drafts replies with an AI model. BullMQ records that today's job completed and stores its return value, perhaps a list of thread IDs and a status string. Tomorrow's job starts from its payload again. It does not know one requester already answered the clarifying question, that a person edited one draft and explained the correction, or that another thread was promised an update today. It can draft the same question again, freshly worded, with complete confidence.
The store operators end up building by hand
The common fix is a second store next to the queue. A Postgres table holds the last summary per customer. Extra Redis keys hold open items, last-seen IDs, and flags for work already done. A helper queries those stores before each job, assembles a briefing, and packs it into the payload at add() time. The memory becomes a side system to design, test, and keep correct as jobs and models change.
That side store also keeps less than the agent needs. A summary row is a run compressed to its ending. The next decision often turns on the middle: the original request, the option that was rejected, the correction a person gave, and the reason the decision went one way instead of another. If only the final output was saved, the next run inherits the conclusion with none of the exchange that produced it.
Scope narrows it further. The table belongs to that one Node.js service. The same operator usually runs agents elsewhere too: another queue, an n8n or Make scenario, and AI tools used directly in chat. Each place keeps its own partial record, and a decision made in one never reaches the morning BullMQ job unless someone copies it across by hand.
A memory that lives outside the job
The cleaner shape is to keep execution in BullMQ and give the agent a memory that lives outside any single job, service, or tool, which every run reads at the start and updates at the end.
Vilix AI is built for that layer. It is cloud-hosted with zero infrastructure to run, so there is no extra store to provision, secure, or keep alive between schedules. It is available over MCP, so the same memory follows the agent across a BullMQ worker, another automation platform, and the AI tools used directly. One memory, reachable everywhere the work happens.
Vilix AI stores full conversation history, not just facts or final results. A scheduled agent can revisit the actual exchange: what was asked, what was tried, what a person corrected, and what was settled. That is the history that stops a second run from asking a settled question again, repeating a follow-up that already went out, or drafting against an instruction that changed in conversation yesterday.
In a BullMQ setup the pattern stays small. Before the worker calls the model, the job retrieves the relevant history for that customer, project, or workflow, does the work with the past in view, and saves the new exchange and outcome back before it completes. The queue keeps scheduling and retrying, Redis keeps holding job records, and the continuing story lives in the memory layer, where the next run in any tool can find it.
Data in Vilix AI can be exported or deleted at any time. The free plan is free forever, and Pro offers a 7-day trial with no credit card required, so the pattern can be tested on one recurring job first.
The short answer
Does BullMQ remember between runs? In the storage sense, yes: pending jobs, completed and failed records, logs, return values, and scheduler patterns all persist in Redis until retention removes them. In the working sense an AI agent needs, no: the next job receives only the payload it was added with and starts fresh, unless your own code fetches the past and rebuilds a briefing for it.
Let BullMQ do queuing, retries, and scheduling. Give the agents inside those jobs a shared memory outside them, and each run can start where the last one actually left off.
Start at Vilix AI and connect one recurring job first.