DocumentationIntroduction

Pidgey

Pidgey

Type-safe background jobs that start simple and scale when you need them.

Pidgey is a progressive job queue for TypeScript developers. Start with SQLite for zero-setup development, use your existing PostgreSQL database in production, and scale to Redis when you need it—all with the same code.

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!',
});

🔄 Progressive Enhancement

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

// Week 1: Development with SQLite
const pidgey = Pidgey({ adapter: 'sqlite' });
 
// Month 1: Production with PostgreSQL
const pidgey = Pidgey({ adapter: 'postgres', connection: DATABASE_URL });
 
// Month 6: High throughput with Redis
const pidgey = Pidgey({ adapter: 'redis', options: { host: 'redis' } });

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 — Database-backed but no escape hatch when you outgrow them

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

→ Read the full comparison

What You Get

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

Next Steps