Free forever, no credit card.Get Started for Free →
← All posts
November 9, 2026 · 6 min read

Does Asynq Remember Between Runs? Tasks Are Stored in Redis. The Next Task Still Starts With Only Its Payload.

Does Asynq Remember Between Runs? Tasks Are Stored in Redis. The Next Task Still Starts With Only Its Payload. Asynq remembers tasks well enough that a queue survives restarts, deploys, and crashed workers. Every task is written to Redis before any worker touches it, so pending work does not live in one process and does not vanish when that process stops. That durability is real, and it is easy to overread. When a worker picks a task up, the handler receives a type name and a payload, and almos

Does Asynq Remember Between Runs? Tasks Are Stored in Redis. The Next Task Still Starts With Only Its Payload.

Asynq remembers tasks well enough that a queue survives restarts, deploys, and crashed workers. Every task is written to Redis before any worker touches it, so pending work does not live in one process and does not vanish when that process stops. That durability is real, and it is easy to overread. When a worker picks a task up, the handler receives a type name and a payload, and almost nothing else. What an earlier task figured out is not in that payload unless earlier code put it there or stored it where the next handler knows to look.

A task is a type plus bytes, not a continuing conversation

Code creates work with asynq.NewTask, giving a type string such as email:deliver and a payload as raw bytes, most often JSON. A client then enqueues that task, immediately, after a delay with ProcessIn, or at a set time. Enqueue options travel with the task: which queue it belongs to, how many times it may be retried, a timeout or deadline, a uniqueness window, and a retention period after success.

The server side polls Redis, leases due tasks to workers, and calls ProcessTask on the handler registered for the type. Inside the handler, the task object exposes the type and the payload, plus context helpers for facts about this delivery itself, such as the retry count and the queue name. That is the whole briefing. There is no field for what the last task of this type concluded, and no automatic link between one task and the next.

Redis holds the task message and its metadata faithfully. It does not add to them while the work runs. A handler that decides an account needs a human review has nowhere in its own task record to leave that decision for tomorrow. The decision leaves with the handler return unless application code stores it deliberately.

What Redis actually keeps between runs

Three kinds of things persist in an Asynq system, and separating them prevents most confusion.

First, the queue itself persists. Tasks sit in Redis in clear states: pending tasks waiting in a queue, active tasks leased to a worker, scheduled tasks waiting for their time, and retry tasks waiting out a back-off delay. A restart does not clear those sets.

Second, the delivery record persists, briefly and on strict terms. When a handler returns an error, the server reschedules the same task for a retry, by default with exponential back-off. When retries are exhausted, the task moves to the archive, kept for inspection until the archive reaches its size limit and the oldest tasks are deleted. Success is shorter lived: by default a successfully processed task is removed from Redis at once. Setting the Retention option keeps it as a completed task for the chosen duration, after which it is deleted automatically. A handler can also write result bytes with the task ResultWriter, stored in Redis alongside the task. That result lives and dies with the task record itself, so it is a way to inspect one outcome, not a store the next task reads.

Third, whatever application code writes for itself persists. A handler can update a database row, write its own Redis key, or enqueue a follow-up task whose payload carries a summary of what just happened. Those writes are the entire bridge between tasks, and every part is manual: choosing what to save, where it lives, and teaching the next handler to fetch it.

Periodic tasks make the boundary easiest to see

Asynq Scheduler turns a cron-style entry into fresh work on a schedule, and that mechanism shows the boundary cleanly. Each time an entry comes due, the scheduler enqueues a new task built from the registered type and payload. Monday's run and Tuesday's run are siblings from the same entry, not one task resuming where it stopped.

A retry is the opposite case. A retry is the same task continuing its own delivery, so its retry count and failure history stay attached to that one record. A periodic run is a new task, so none of that travels forward. The schedule is shared. The execution record is not.

The Unique option underlines the same point. For its time window, Asynq locks a combination of task type, payload, and queue so a duplicate cannot be enqueued. That guard stops the same instruction arriving twice. It says nothing about what a previous instruction learned while it ran.

Where an AI step inside an Asynq task goes blind

Add a model call inside a handler and the gap stops being a design detail. Consider a nightly task that reviews new support conversations, drafts replies, and flags accounts that need attention. On the first night the handler reads its payload, calls the model, and produces useful judgments: this account was already offered a refund, that conversation was already taken over by a human, this question was already answered last week in a different tool.

On the second night a new task arrives from the scheduler. Its payload carries a date, an account ID, perhaps a batch size. It does not carry last night judgments, unless last night handler wrote them into a store and tonight handler queries that store before calling the model. Without that hand-built loop, the step repeats work already done and can contradict a decision another run already made. The queue did its job perfectly. Remembering was never part of its job.

Give the task a memory it can read before it reasons

The useful split is between delivering work and remembering work. Asynq handles delivery well, with Redis-backed queues, retries, scheduling, and archiving. Remembering needs a memory layer that every run, and every tool around the run, can read and write in one place.

Vilix AI is built for that second job. Vilix AI is cloud-hosted, so there is zero infrastructure to deploy or manage alongside Redis. The same memory is available everywhere over MCP, so an Asynq handler, 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.

For a nightly review task, the change is simple. Before the model reasons, the handler retrieves relevant memory: prior decisions for that account, earlier conversations, and rules settled in other tools. After the handler acts, it saves what it did and learned back to the same memory. The next run starts from that record instead of from its payload 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.

Asynq will keep remembering what it was designed to remember: a type, a payload, a delivery state, and a short-lived record of how that one task ended. Give the AI steps inside those tasks a memory designed for reasoning, and each run stops starting blind.

Get Started for Free

Persistent memory across ChatGPT, Claude, and the AI tools you already use in Vilix AI.

Get Started for Free

Free forever, no credit card.

Keep reading
Does Graphile Worker Remember Between Runs? A Successful Job Is Deleted, and Its Return Value Is Stored Nowhere.

Does Graphile Worker Remember Between Runs? A Successful Job Is Deleted, and Its Return Value Is Stored Nowhere. Graphile Worker stores every job as a row in PostgreSQL, so the queue itself is durable, inspectable, and transactional. That durability creates a natural assumption: if the jobs live in a real database, the next run of a job should be able to look back at the last run. It cannot. Graphile Worker keeps a job only while the job still needs to run. The moment a job succeeds, its row is

Does Huey Remember Between Runs? The Result Store Deletes on Read, and Periodic Tasks Discard Their Return.

Does Huey Remember Between Runs? The Result Store Deletes on Read, and Periodic Tasks Discard Their Return. Huey keeps three things in its storage backend: a queue of pending task calls, a schedule of delayed and periodic work, and a result store for return values. Because all three can live in Redis, Postgres, or SQLite, it is easy to assume the next run of a task can see what the last run produced. It cannot, at least not in the way an AI task needs. Huey stores delivery state and one return

Does River Remember Between Runs? Jobs Are Stored in Postgres. The Next Job Still Starts With Only Its Args.

Does River Remember Between Runs? Jobs Are Stored in Postgres. The Next Job Still Starts With Only Its Args. River remembers jobs in Postgres, in the same database as the application data. That design is the reason teams choose it: a job can be inserted inside the same transaction as the changes it relates to, so the job exists if the transaction commits and disappears if it rolls back. Every job sits as a row in the river_job table. That durability makes a second assumption feel safe, that the