DocumentationIntroduction

Pidgey

Pidgey

Type-safe background jobs that start simple and scale with you.

Pidgey is a type-safe job queue for TypeScript and Next.js apps. It lets you add background jobs with zero setup locally, run reliably in production, and scale to high-throughput workloads — all without rewriting your code.

Under the hood, Pidgey can run on SQLite, PostgreSQL, or Redis. You choose the adapter that fits your workload.

Key Features

🎯 Type-Safe Everything

Full end-to-end type inference from job definition to enqueueing. TypeScript catches errors before they reach production.

export const sendEmail = pidgey.defineJob({
  name: 'send-email',
  handler: async (data: { to: string; subject: string }) => {
    await emailService.send(data);
  },
});
 
// ✅ Full autocomplete and type checking
await sendEmail.enqueue({
  to: 'leslie.knope@pawnee.gov',
  subject: 'Welcome!',
});

🔄 Flexible Backend Options

Start simple, add complexity only when needed. Same code, just change your adapter:

// Local development with SQLite
const pidgey = Pidgey({ adapter: 'sqlite' });
 
// Production workloads with PostgreSQL
const pidgey = Pidgey({ adapter: 'postgres', connection: DATABASE_URL });
 
// High-throughput scenarios with Redis
const pidgey = Pidgey({ adapter: 'redis', options: { host: 'redis' } });

Each backend has tradeoffs. Redis excels in throughput and bursty workloads, but many production systems run Pidgey successfully on Postgres alone.

Your jobs, handlers, and application code never change.

⚡ Next.js Native

File-based job discovery—just like Next.js routes. One file per job, automatic discovery. Plus Server Actions support and zero-config setup for App Router.

'use server';
 
import { sendEmail } from '@/jobs/send-email';
 
export async function signup(email: string) {
  await sendEmail.enqueue({ to: email, subject: 'Welcome!' });
}

Run npx pidgey worker dev and all jobs in your jobs/ directory are automatically discovered.

Quick Start

npm install @pidgeyjs/core @pidgeyjs/next @pidgeyjs/sqlite

1. Create config and client:

pidgey.config.ts
export default defineConfig({ adapter: 'sqlite', filename: './pidgey.db' });
lib/pidgey.ts
import { Pidgey } from '@pidgeyjs/next';
import config from '../pidgey.config';
 
export const pidgey = Pidgey(config);

2. Define a job:

jobs/send-email.ts
import { pidgey } from '@/lib/pidgey';
 
export const sendEmail = pidgey.defineJob({
  name: 'send-email',
  handler: async (data: { to: string; subject: string }) => {
    console.log(`Sending email to ${data.to}`);
    return { sent: true };
  },
});

3. Enqueue from anywhere:

await sendEmail.enqueue({ to: 'leslie.knope@pawnee.gov', subject: 'Welcome!' });

4. Start the worker:

npx pidgey worker dev

→ Full setup guide

Why Pidgey?

Most job queue solutions force you to choose between simplicity and scalability:

  • Managed services — Great DX but vendor lock-in and monthly bills
  • Redis-based queues — Powerful but require infrastructure before you write your first job
  • Postgres-native queues — Solid for a single database, but hard to evolve as workload requirements change

Pidgey gives you both: Start with zero infrastructure, scale without rewriting.

→ Read the full comparison

What You Get

  • ✅ Automatic retries with exponential backoff
  • ✅ Failed job tracking and bulk retry
  • ✅ Job lifecycle hooks and status tracking
  • ✅ Scheduled (cron) jobs with pause/resume support
  • ✅ Delayed job scheduling
  • ✅ Concurrency control
  • ✅ Multiple queue support
  • ✅ Type-safe job definitions
  • ✅ Self-hosted (your infrastructure, your data)

Next Steps


Made with ❤️ in Chicago