Many Pega apps still have a Standard Agent quietly chugging away in the background, sending confirmation emails or polling a staging table, written by someone who learned Pega before Queue Processors existed and never had a reason to relearn this part. Agents — both Standard and Advanced — are deprecated, and upgrades across major versions can disable or remove them outright, including the well-known pyProcessSLA cases people forget are agent-driven. The replacements are Queue Processors and Job Schedulers, and the mistake that turns up almost as often as "still on Agents" is "migrated off Agents, but picked the wrong one of the two."

This post covers the distinction that decides between them, and the pattern for decoupling a bulk data feed from the rate at which Pega can safely create cases. It follows on from the File Listener vs API vs Kafka comparison: that post is about how records get into Pega, this one is about what happens next.

Async work is an event-or-clock decision

The split that matters day to day isn't "old versus new", it's event-driven versus time-driven. A Queue Processor exists because something happened: a case advanced, a record landed on a queue, an integration call needs to run asynchronously. A Job Scheduler exists because a clock struck a certain time: a nightly reconciliation, an hourly poll of a legacy table. Pega gives you the trigger in both cases, but what you get around the trigger differs a lot.

Here is the summary table. Treat it as a starting point rather than a ranking: the right choice depends on what actually kicks the work off, how failures should be handled, and what your Pega version supports.

PrimitiveTriggerFailure handlingStatus
Standard AgentPolling loop on an intervalManual — you build your own retry and error logicDeprecated, replaced by Queue Processors
Advanced AgentPolling loop on an interval, more configuration surfaceManualDeprecated, replaced by Job Schedulers
Queue ProcessorAn item landing on a queueBuilt-in retry and exception handlingCurrent, event-driven
Job SchedulerFixed time or recurring scheduleYou still build your own failure handlingCurrent, time-driven

The built-in retry and exception handling is the single biggest reason to prefer a Queue Processor over hand-rolling that logic. A Job Scheduler gives you the scheduling, but the failure handling is still on you, exactly as it was with an Advanced Agent.

Framed this way, "Queue Processor or Job Scheduler?" stops being a coin flip: ask whether the thing that should start the work is an event or a time. If your honest answer is "both, sort of" — which is common with bulk feeds — that usually means you need one of each, wired together.

The pattern: decoupling intake rate from case-creation rate

This comes up constantly with bulk feeds. Whatever gets the raw data into Pega — a File Listener run, an API call, a Kafka Data Flow — can land records faster than it is safe to create cases from them, especially once you factor in contention on case creation itself. Rather than let intake pressure turn directly into case-creation pressure, put a staging table in between.

Staging table pattern: intake, Job Scheduler, Queue Processor An intake source such as a File Listener, API or Kafka Data Flow writes rows with status PENDING into a staging table. A Job Scheduler selects a batch of PENDING rows, marks them QUEUED and adds one queue item per row. A Queue Processor with a tuned thread count consumes the items, creates the cases, and marks each staging row DONE or FAILED. Intake Staging Clock Event Pega case persistence File / API / Kafka runs at feed speed Staging table status = PENDING Job Scheduler batch to QUEUED Queue Processor N threads per node Cases queue items marks the row DONE or FAILED with an error reason A spike in the feed becomes rows waiting in PENDING, not a burst of simultaneous case-creation transactions.

Diagram: the staging table absorbs intake spikes; the Queue Processor's thread count, not the feed, sets the case-creation rate.

In plain steps, the flow is:

1. File Listener / API / Kafka Data Flow
      -> writes raw rows into a staging table (status = 'PENDING')

2. Job Scheduler (e.g. every 60 seconds)
      -> selects a batch of PENDING rows
      -> marks them 'QUEUED'
      -> adds one queue item per row (Add-To-Queue)

3. Queue Processor (N threads, tuned per node)
      -> consumes queue items
      -> creates the case
      -> marks the staging row 'DONE' or 'FAILED' with an error reason

Nothing about intake changes: the File Listener or Kafka Data Flow runs as fast as it always did. What changes is that case creation now happens at a rate the Queue Processor's thread count controls. If the feed spikes, the staging table absorbs it as rows sitting in PENDING, rather than as a burst of cases fighting over the same locks. This is a design pattern, not a built-in Pega feature, so the status columns, batch size and schedule interval are all yours to design and tune.

Tuning the Queue Processor

The thread count isn't a global dial. It is configured per node, so your throughput ceiling is roughly threads per node × number of nodes running that Queue Processor. How that is configured differs between Pega versions and deployments, so check the documentation for yours. A few things worth checking on any inherited Queue Processor:

Where a Job Scheduler is the right call on its own

Not every background job needs the staging-table pattern. It earns its complexity specifically when intake rate and processing rate must be decoupled. A Job Scheduler by itself is still the right tool for work that is genuinely "run this on a clock": a nightly reconciliation report, an hourly poll of a legacy mainframe table with no event model at all, a weekly archival sweep.

Reaching for a Queue Processor there just because it's the modern option adds an eventing layer around work that was never event-shaped. The flip side is just as common: a Job Scheduler that polls for "anything new" and then processes every item in one long run is quietly rebuilding a Queue Processor without the retries.

Migrating off Agents

If you've inherited Standard or Advanced Agents, don't treat the migration as a drop-in rename. Before you touch anything:

Production considerations: beyond choosing the primitive

Picking between a Queue Processor and a Job Scheduler is the easy part. The things that take the time are the ones below, and they apply whichever you choose.

A decision framework, not a rule of thumb

Before choosing, answer these questions about the work, in this order:

Only after those do thread counts and node types come into it. The table near the top is a place to start; it is not a ranking.

Lessons learned