What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Strict priority can starve lower-priority jobs indefinitely if higher-priority work keeps arriving fast enough to use all available processing capacity. PostgreSQL’s FOR UPDATE SKIP LOCKED helps workers claim rows without waiting on one another; it does not make a priority policy fair. Prevent starvation by defining a fairness rule—typically priority aging or weighted fair queuing—and keep the claim-and-state-change operation atomic.
What starvation means in a priority queue
A strict-priority scheduler always prefers a job in a higher-priority class over one in a lower class. If top-priority jobs arrive continuously and consume all worker capacity, lower-priority jobs may remain pending indefinitely. A FIFO tie-breaker within each class does not solve this cross-class problem.
First decide what “prevent starvation” should mean for your service: eventual promotion, a minimum share of claim opportunities, or a maximum wait. Aging can make a waiting job increasingly competitive; weighted scheduling can reserve a configured share of claims for each band. A hard waiting-time bound is different: it depends on arrival rates, job duration, available workers, and failures, so neither policy alone establishes a deadline.
Also decide where fairness applies: across the whole queue, separately within each queue, or across tenants as well as priority bands. If one tenant can continuously submit urgent work, priority-band fairness alone may still leave other tenants disadvantaged.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minute#1 Best Overall
Choose a fairness policy
| Policy | How it addresses starvation | Main trade-off | Useful when |
|---|---|---|---|
| Strict priority with FIFO tie-break | It does not guarantee progress across priority classes. | Urgent work gets the strongest preference, but lower bands can starve. | Urgent work must dominate and its arrival volume is bounded. |
| Priority aging | A job’s effective priority rises as it waits. | More fairness weakens strict urgency; materialized updates add writes, while query-time calculations can complicate ordering and indexing. | Waiting jobs should eventually become competitive. |
| Weighted fair queuing | Each nonempty priority band receives a configured share of claim opportunities. | Requires allocation logic and does not guarantee when jobs finish. | Each class needs a predictable slice of dequeue capacity. |
| Head-of-line leases within a band | Workers do not pass an actively leased head item to claim later items in that band. | A slow or leased head can leave capacity idle behind it. | Per-band ordering matters more than maximum parallelism. |
These are scheduling patterns, not PostgreSQL features or benchmark results. The best fit depends on the service’s ordering requirements, workload, and tolerance for operational complexity.
Priority aging
Track when a job became eligible, then raise its effective priority by defined waiting intervals, stopping at the highest class. For example, Awa’s ADR-005 documents a 60-second default aging interval and promotes a priority-4 job one level per interval until it reaches priority 1. Those are Awa’s configuration choices, not general recommendations; shorter intervals strengthen fairness while reducing how strongly original urgency controls the order. See Awa ADR-005.
Aging can be calculated when selecting jobs or materialized by a periodic task. A task that updates stored priorities can simplify the dequeue ordering, but it adds writes and must keep running reliably. Batch updates, change only rows whose effective priority changes, make retries safe, and alert if the task or its leader stops. Preserve original priority separately if operators need to understand why a job’s effective priority changed; in-place updates can obscure that history.
Rank #2
Weighted fair queuing
Divide work into priority bands and allocate each dequeue batch according to configured weights. DataHub’s pgQueue documentation gives an example with weights of 70/20/10 across three bands: for a batch of ten, up to 7/2/1 claims can go to the bands, with unused slots redistributed when a band is empty. These are example settings, not measured results or universal defaults. See DataHub pgQueue documentation.
The share applies to claim opportunities, not completion deadlines. Batch size and polling frequency affect how closely small batches can match the configured proportions; concurrency, job duration, and a saturated worker pool also affect completion behavior. Validate the policy against representative traffic rather than inferring finish-time guarantees from the weights.
Claim jobs safely with concurrent workers
PostgreSQL documents SKIP LOCKED as a way for concurrent consumers to avoid waiting on rows locked by other transactions; it also warns that this produces an inconsistent view, which is suitable for queue-like access but not for general-purpose reads. It is a claiming mechanism, not a fairness policy. See the PostgreSQL SELECT documentation.
Rank #3
A common pattern is to select eligible rows in deterministic order, lock them with FOR UPDATE SKIP LOCKED, and mark them claimed in the same short transaction. Commit before running the jobs; holding row locks for the duration of the work can block other activity. If a worker may disappear mid-job, use a recoverable lease or visibility timeout with a retry or reaper policy. PostgreSQL documents locking behavior, not a complete job-queue protocol.
WITH picked AS (
SELECT id
FROM jobs
WHERE state = 'ready'
AND available_at <= now()
ORDER BY effective_priority ASC, available_at ASC, id ASC
FOR UPDATE SKIP LOCKED
LIMIT $1
)
UPDATE jobs AS j
SET state = 'running', claimed_at = now(), worker_id = $2
FROM picked
WHERE j.id = picked.id
RETURNING j.*;
This is an illustrative atomic claim-and-update shape, not a drop-in queue implementation. The direction of priority ordering, state names, lease fields, retry behavior, transaction assumptions, and fairness policy must match your schema and service. Confirm the behavior of the PostgreSQL version you deploy and inspect the plan on representative data.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Under concurrent claims, a worker can skip a locked high-ranked row and claim a later one. That can improve throughput, but it weakens strict global ordering. If strict head ordering within a priority band matters more than parallelism, a head-of-line lease design can stop at the leased head rather than pass it. DataHub documents this kind of trade-off for sequence ordering within a priority.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Keep the dequeue order index-friendly
Use an explicit, deterministic order: for example, effective priority, eligible time, and a unique ID. Align indexes with the queue’s equality filters, priority order, and tie-break columns. A partial index limited to claimable rows can reduce the hot index set. PostgreSQL B-tree indexes can provide ordered output in suitable plans, but the benefit depends on predicates, data distribution, and planner choices; verify with EXPLAIN (ANALYZE, BUFFERS).
One project’s example index is (queue, priority, run_at, id) WHERE state = 'available', paired with its own claim ordering. Treat it as an example rather than a universal schema. See Awa ADR-005 and the PostgreSQL documentation on indexes and ordering.
If effective priority is calculated dynamically from elapsed wait time, the ordering expression may not match a simple index. Materializing the effective value can restore a simpler ordering path, at the cost of the maintenance writes described above.
Measure starvation and validate the policy
Total throughput can look healthy while one band accumulates old work. Track enough metrics to see both queue health and scheduling decisions:
- Queue depth and oldest eligible-job age by priority band.
- Claim counts and completion rates by band.
- Retries and lease expirations.
- Aging promotions or fair-share allocation decisions.
Alert on sustained growth in the oldest eligible age, even when overall throughput remains high. Test representative arrival bursts and worker concurrency, and inspect the actual claim-query plan. There is no universal benchmark or starvation threshold established by the cited sources; set service objectives from your own workload.
Quick Recap
Put the policy into practice
- State the fairness objective. Choose eventual promotion, a minimum share of claims, or a service-specific waiting objective. Do not imply a deadline unless workload assumptions support it.
- Select aging or weighted shares. Use aging when waiting should improve a job’s rank; use weighted scheduling when each band needs a defined slice of claim capacity.
- Keep claiming atomic. In a short transaction, select and lock eligible rows, update ownership or state, then commit before processing jobs.
- Align indexes with the real order. Include queue filters and deterministic tie-breakers; check whether dynamic effective-priority calculations prevent the intended index from being used.
- Test and monitor by band. Exercise realistic arrivals, concurrency, retries, and job durations; watch oldest eligible age as well as claims and completions.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




