Job queue for Next.js that uses your existing database. SQLite for dev, Postgres for prod, Redis when you scale.
npm install @pidgeyjs/core @pidgeyjs/next @pidgeyjs/sqlite
// jobs/send-email.ts
import { pidgey } from '../lib/pidgey';
export const sendEmail = pidgey.defineJob({
name: 'send-email',
handler: async (data: { to: string }) => {
await sendEmailService(data.to);
},
});
// Enqueue from anywhere
import { sendEmail } from '@/jobs/send-email';
await sendEmail.enqueue({ to: 'user@example.com' });Most job queues need Redis or a managed service. You already have a database.
Mock servers, tunnels, Docker. Just use SQLite locally.
Start with Postgres, switch to Redis when you need scale. Same code, no refactoring.
Just like Next.js routes. One file per job, automatic discovery.
Full TypeScript inference from job definition to enqueue.
SQLite → Postgres → Redis. Same code, different backend.
Your infrastructure, your data. No vendor lock-in.
Exponential backoff, configurable attempts.
Failed jobs preserved for debugging.
Schedule jobs to run later with delay options.
Test handlers as plain functions, no mocking required.
Same API, different backends. Start simple, scale when needed.
// pidgey.config.ts
import { defineConfig } from '@pidgeyjs/core';
export default defineConfig({
adapter: 'sqlite',
filename: './pidgey.db',
});
// Perfect for development
// Zero dependencies
// File-based persistenceOutgrow Postgres? Switch to Redis with one config change. Same jobs, no refactoring.
File-based jobs that just work.
npm install @pidgeyjs/core @pidgeyjs/next @pidgeyjs/sqlite// pidgey.config.ts
import { defineConfig } from '@pidgeyjs/core';
export default defineConfig({
adapter: 'sqlite',
filename: './pidgey.db',
worker: {
jobsDir: 'jobs',
concurrency: 10,
},
});// jobs/send-welcome-email.ts
import { pidgey } from '@/lib/pidgey';
export const sendWelcomeEmail = pidgey.defineJob({
name: 'send-welcome-email',
handler: async (data: { userId: string }) => {
const user = await db.user.findUnique({
where: { id: data.userId }
});
await sendEmail({
to: user.email,
subject: 'Welcome!',
});
},
config: {
retries: 3,
timeout: 30000,
},
});// app/actions/signup.ts
'use server';
import { sendWelcomeEmail } from '@/jobs/send-welcome-email';
export async function signup(email: string) {
const user = await db.user.create({ data: { email } });
// Job runs in background
await sendWelcomeEmail.enqueue({ userId: user.id });
return user;
}