---
name: tl-pg-boss-7db7a1e9f55f
description: PostgreSQL-backed job queue with exactly-once delivery using SKIP LOCKED. Use when adding background jobs, task scheduling, cron jobs, or async processing to Node.js apps already using Postgres.
license: MIT
metadata:
  version: "1.1"
  author: Todd Levy <toddlevy@gmail.com>
  homepage: https://github.com/toddlevy/tl-agent-skills
  quilted:
    - source: triggerdotdev/skills/trigger-tasks
      weight: 0.15
      description: Async workflow patterns, retry strategies, cron scheduling
    - source: omer-metin/skills-for-antigravity/pg-boss
      weight: 0.10
      description: SKIP LOCKED principles, archiving patterns
  moment: implement
  surface:
    - api
    - db
  output: patch
  risk: low
  posture: guided
  agentFit: repo-write
  dryRun: partial
---

<!-- Copyright (c) 2026 Todd Levy. Licensed under MIT. SPDX-License-Identifier: MIT -->

# tl-pg-boss

PostgreSQL-backed job queue for Node.js with exactly-once delivery, cron scheduling, and transactional safety.

## When to Use

- "Add background jobs to my app"
- "I need a job queue but already use Postgres"
- "Set up cron jobs / scheduled tasks"
- "Process async work with retries"
- User mentions: job queue, background processing, task scheduling, worker

### When to Consider Alternatives

For **managed background jobs with dashboard UI**, consider [Trigger.dev](https://trigger.dev) instead. pg-boss is best when:
- You want self-hosted, PostgreSQL-native job queues
- You already have Postgres and don't want external dependencies
- You need transactional job enqueuing (same transaction as your data writes)
- Cost matters (pg-boss is free, managed services charge per job)

Trigger.dev is better when:
- You need a polished dashboard out of the box
- You want managed infrastructure with auto-scaling
- Your team prefers a hosted SaaS experience
- You need complex workflows with visual orchestration

## Outcomes

- **Patch**: pg-boss installed and configured with typed job handlers
- **Artifact**: Job definitions with proper queue setup
- **Decision**: Queue structure, job patterns, monitoring approach

---

## Requirements

| Requirement | Version |
|-------------|---------|
| Node.js | 22.12+ |
| PostgreSQL | 13+ |
| Privilege | CREATE on database |

---

## Installation

```bash
pnpm add pg-boss
```

Auto-creates `pgboss` schema on first `start()`. No manual migrations needed.

---

## Core Concepts

### SKIP LOCKED

PostgreSQL's `SKIP LOCKED` provides exactly-once delivery without distributed transactions.

### Always Call `start()`

**Critical**: Every process must call `start()`, even producers.

```typescript
const boss = new PgBoss(connectionString);
await boss.start(); // Required in EVERY process
```

Even with multiple processes calling `start()`, only one runs supervision.

### One Queue Per Job Type

```typescript
await boss.createQueue("send-email");
await boss.createQueue("process-image");
```

---

## Basic Setup

```typescript
import { PgBoss } from "pg-boss";

const boss = new PgBoss({
  connectionString: process.env.DATABASE_URL,
  schema: "pgboss",
});

boss.on("error", console.error);
await boss.start();
await boss.createQueue("my-queue");
```

---

## Job Patterns

### Send a Job

```typescript
const jobId = await boss.send("my-queue", { userId: "123" });
```

### Send with Options

```typescript
await boss.send("my-queue", payload, {
  retryLimit: 3,
  retryDelay: 60,
  expireInMinutes: 30,
  priority: 1,
});
```

> **Full options**: See `references/send-options.md`

### Delayed Job

```typescript
await boss.send("my-queue", payload, {
  startAfter: new Date(Date.now() + 60000),
});
```

### Cron Scheduling

```typescript
await boss.schedule("daily-report", "0 9 * * *", { type: "daily" });
```

### Unschedule (Remove Cron)

```typescript
await boss.unschedule("daily-report");
```

> **Schedule management**: See `references/schedule-management.md`

---

## Worker Patterns

### Basic Worker

```typescript
await boss.work("my-queue", async ([job]) => {
  console.log(`Processing ${job.id}`);
  // Auto-completes on return, throw to fail
});
```

**Note**: Callback receives an **array** even with `batchSize: 1`.

### Batch Processing

```typescript
await boss.work("bulk-import", { batchSize: 10 }, async (jobs) => {
  for (const job of jobs) {
    await processItem(job.data);
  }
});
```

### Typed Jobs

```typescript
interface EmailJob {
  to: string;
  subject: string;
}

await boss.send<EmailJob>("send-email", { to: "user@example.com", subject: "Hi" });

await boss.work<EmailJob>("send-email", async ([job]) => {
  await sendEmail(job.data.to, job.data.subject);
});
```

> **TypeScript patterns**: See `references/typescript-patterns.md`

---

## Queue Configuration

### Dead Letter Queue

```typescript
await boss.createQueue("my-queue", { deadLetter: "my-queue-dlq" });
await boss.createQueue("my-queue-dlq");
```

### Retention

```typescript
await boss.createQueue("my-queue", { retentionMinutes: 60 * 24 });
```

---

## Fastify Integration

```typescript
import Fastify from "fastify";
import { PgBoss } from "pg-boss";

const fastify = Fastify();
const boss = new PgBoss(process.env.DATABASE_URL);

fastify.decorate("boss", boss);

fastify.addHook("onReady", async () => {
  boss.on("error", fastify.log.error.bind(fastify.log));
  await boss.start();
  await boss.createQueue("my-queue");
  await boss.work("my-queue", handler);
});

fastify.addHook("onClose", async () => {
  await boss.stop({ graceful: true });
});
```

---

## Monitoring

### Dashboard

```bash
pnpm add @pg-boss/dashboard
DATABASE_URL="postgres://..." npx pg-boss-dashboard
```

### Quick SQL

```sql
-- Pending by queue
SELECT name, COUNT(*) FROM pgboss.job WHERE state = 'created' GROUP BY name;

-- Failed jobs
SELECT * FROM pgboss.job WHERE state = 'failed' ORDER BY completedon DESC LIMIT 20;
```

> **Full monitoring**: See `references/monitoring.md`

---

## Sharp Edges

| Gotcha | Solution |
|--------|----------|
| Must call `start()` everywhere | Even producers need it |
| Jobs array in worker | Use `([job])` not `(job)` |
| No LISTEN/NOTIFY | Polling only, set `pollingIntervalSeconds` |
| Schema needs CREATE privilege | Or use CLI: `npx pg-boss migrate --dry-run` |
| Once completed, can't fail | Don't mix `work()` with manual `fail()` |
| No `pauseQueue()` in v10 | Use `unschedule()` + direct SQL |
| Schedules re-register on restart | Code calls `schedule()` on init; unschedule is temporary |

---

## Best Practices

1. **Set expiration** to prevent zombies: `expireInMinutes: 30`
2. **Archive aggressively** with retention policies
3. **Idempotent handlers** using upserts
4. **Graceful shutdown**: `boss.stop({ graceful: true })`

---

## Observability

> See [Observability](references/observability.md) for Prometheus gauge/counter setup with `prom-client` and Prometheus alerting rules for queue backlog and failure rate.

---

## Testing Patterns

> See [Testing Patterns](references/testing-patterns.md) for unit testing job handlers, integration testing with a real PostgreSQL database, and mocking pg-boss in vitest.

---

## Kubernetes Deployment

> See [Kubernetes Deployment](references/kubernetes-deployment.md) for a worker Deployment manifest with resource limits, liveness probe, preStop hook, and the SIGTERM graceful-shutdown handler.

---

## Verification

1. [ ] `boss.start()` completes without error
2. [ ] `boss.createQueue()` succeeds
3. [ ] `boss.send()` returns a job ID
4. [ ] Worker processes the job
5. [ ] Job state changes to `completed`

---

## References

### Quilted Skills

- [triggerdotdev/skills/trigger-tasks](https://skills.sh/triggerdotdev/skills/trigger-tasks) — Workflow patterns
- [omer-metin/skills-for-antigravity/pg-boss](https://playbooks.com/skills/omer-metin/skills-for-antigravity/pg-boss) — SKIP LOCKED principles

### First-Party Documentation

- [pg-boss GitHub](https://github.com/timgit/pg-boss) — Official repository
- [pg-boss API Docs](https://timgit.github.io/pg-boss/) — API reference
- [pg-boss Dashboard](https://github.com/timgit/pg-boss/tree/master/packages/dashboard) — Web UI

### PostgreSQL Resources

- [PostgreSQL SKIP LOCKED](https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE) — Locking semantics
- [PostgreSQL Advisory Locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS) — Application-level locks
- [Connection Pooling with PgBouncer](https://www.pgbouncer.org/) — Connection management

### Alternative Solutions

- [Graphile Worker](https://worker.graphile.org/) — PostgreSQL queue alternative
- [Trigger.dev](https://trigger.dev/docs/) — Managed background jobs
- [BullMQ](https://docs.bullmq.io/) — Redis-based alternative

### Skill References

- `references/send-options.md` — Full send options
- `references/typescript-patterns.md` — BaseJob, JobManager
- `references/monitoring.md` — Dashboard + SQL queries
- `references/advanced-patterns.md` — Singleton, throttling, pub/sub
- `references/schedule-management.md` — Cron schedules, unschedule, pause patterns
- `references/wordpress-migration.md` — WP-Cron & Action Scheduler mapping

---

## Attribution

| Source | Author | Contribution |
|--------|--------|--------------|
| [pg-boss](https://github.com/timgit/pg-boss) | Tim Gilbert (@timgit) | Core library, official docs |
| [TypeScript Deep Dive](https://logsnag.com/blog/deep-dive-into-background-jobs-with-pg-boss-and-typescript) | Shayan (@ImSh4yy) | BaseJob class, JobManager pattern |
| [pg-boss-admin-dashboard](https://github.com/lpetrov/pg-boss-admin-dashboard) | Lyubomir Petrov (@lpetrov) | Alternative dashboard with JMESPath |


---
Source attribution: toddlevy
Original project: https://github.com/toddlevy/tl-agent-skills/blob/0fdf6a1ab28bb40eb9f5d717635617ccf5878dc6/skills/tl-pg-boss/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Mega AI Hub.

## Upstream license notice

MIT License

Copyright (c) 2026 toddlevy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


## Additional upstream notices

tl-pg-boss-7db7a1e9f55f/DAVEAI-UPSTREAM-NOTICE

tl-agent-skills
Copyright (c) 2026 Todd Levy

This product includes material derived from the following upstream sources,
used under their respective licenses or terms of use. See each skill's
metadata.quilted block (inside its SKILL.md frontmatter) for per-source
weights and the precise scope of borrowing.

Skill: tl-complexity-assessment
  - trailofbits/skills/code-maturity-assessor
  - tl-agent-skills/codebase-audit
  - obra/superpowers/systematic-debugging
  - obra/superpowers/verification-before-completion
  - rmyndharis/antigravity-skills/code-refactoring-refactor-clean

Skill: tl-docs-audit
  - openai/openai-agents-python/docs-sync
  - vercel/next.js/update-docs
  - jezweb/claude-skills/docs-workflow
  - local/codebase-audit
  - plaited/development-skills/code-documentation

Skill: tl-docs-create
  - google-gemini/gemini-cli/docs-writer
  - shpigford/skills/readme
  - getsentry/skills/agents-md
  - softaworks/agent-toolkit/crafting-effective-readmes
  - itechmeat/llm-code/changelog
  - patricio0312rev/skills/api-docs-generator
  - remotion-dev/remotion/writing-docs
  - plaited/development-skills/code-documentation
  - aj-geddes/useful-ai-prompts/markdown-documentation
  - local/jambase-docs
  - local/agents-md-create

Skill: tl-docs-viewer-create
  - vercel/streamdown/streamdown
  - remotion-dev/remotion/writing-docs
  - vercel/components.build/building-components

Skill: tl-first-principles
  - sickn33/antigravity-awesome-skills/software-architecture
  - athola/claude-night-market/code-quality-principles
  - ramziddin/solid-skills

Skill: tl-knip
  - brianlovin/claude-config/knip
  - laurigates/claude-plugins/knip-dead-code-detection
  - artivilla/agents-config/knip
  - knoopx/pi/knip
  - pproenca/dot-skills/knip-deadcode-best-practices

Skill: tl-kysely-patterns
  - https://github.com/gallop-systems/claude-skills/skills/kysely-postgres
  - https://kysely.dev/llms.txt
  - https://github.com/TerminalSkills/skills/skills/kysely
  - https://github.com/kysely-org/kysely/issues
  - https://kysely-org.github.io/kysely-apidoc
  - https://agentskills.so/skills/bobmatnyc-claude-mpm-skills-kysely

Skill: tl-live-music-data
  - firecrawl/cli/firecrawl-scrape
  - local://jambase-local-replica-guide
  - local://colitas-data-enrichment
  - local://colitas-local-dev-setup

Skill: tl-openmeter-api-mcp-server
  - anthropics/skills/mcp-builder

Skill: tl-pg-boss
  - triggerdotdev/skills/trigger-tasks
  - omer-metin/skills-for-antigravity/pg-boss

Skill: tl-project-records
  - d6veteran/devlog-skill
  - josephmiclaus/skill-devlog
  - skillrecordings/adr-skill (no license; paraphrased only)
  - product-on-purpose/pm-skills (Apache-2.0; paraphrased only)
  - alirezarezvani/claude-skills
  - stealth-factory/skills
  - SkillMedev/skills
  - jotafurtado/dev-skills
  - skrrt-sh/skills

Skill: tl-schema-org
  - https://playbooks.com/skills/openclaw/skills/schema-markup
  - https://playbooks.com/skills/openclaw/skills/schema-markup-generator
  - https://schema.org/docs/
  - https://developers.google.com/search/docs/appearance/structured-data
  - https://w3c.github.io/json-ld-bp/


# Mega AI Hub resource metadata

Creator / publisher: toddlevy
Original project: https://github.com/toddlevy/tl-agent-skills/blob/0fdf6a1ab28bb40eb9f5d717635617ccf5878dc6/skills/tl-pg-boss/SKILL.md
Attribution basis: Source repository record

Fields of work: Development & Engineering
Roles: Backend Developer, Data Engineer, DevOps / SRE
Specialties: API, Backend, Database, DevOps, Word Documents, Frontend, Git, Testing
Tools: PostgreSQL
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: 0459b517e8e9a1b080009ce073101db0f423a3a428d2f06507291b21dcf0ae97
