All skills
upstash avatar

/upstash-qstash-js

@36daab8
by upstashupstash/skills27 stars
7

Work with the @upstash/qstash TypeScript/JavaScript SDK, an HTTP-based message queue, task scheduler, and background job system for serverless and edge runtimes (Next.js, Vercel, Cloudflare Workers, Deno, Node.js). Use when publishing messages to HTTP endpoints or URL groups, running background jobs without a long-running worker process, scheduling with cron expressions, delaying messages, building FIFO queues with parallelism and flow control, configuring retries and callbacks, handling a dead letter queue (DLQ), deduplicating messages, fanning out to multiple endpoints, verifying QStash webhook signatures (Next.js App Router, Pages Router, and Edge Runtime), running a local QStash dev server, or migrating regions. Also use when the user asks for a serverless cron job, async task queue, job scheduler, delayed delivery, webhook delivery with retries, or event-driven messaging between services.

Use this Skill: https://skilld.dev/gh/upstash/skills/upstash-qstash-js

This session only. Nothing lands on disk.

verificationplatform-specificnextjs.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Next.js Endpoint Verification

Overview

Next.js applications can use QStash in both App Router (route handlers) and Pages Router (API routes). The SDK provides dedicated verification utilities for each.

App Router Verification

Using verifySignatureAppRouter

The SDK provides verifySignatureAppRouter for App Router route handlers:

import { verifySignatureAppRouter } from "@upstash/qstash/nextjs";

// app/api/webhook/route.ts
export const POST = verifySignatureAppRouter(async (req) => {
  const body = await req.json();

  // Request is verified - process it
  console.log("Received verified message:", body);

  return new Response("OK", { status: 200 });
});

With Custom Configuration

import { verifySignatureAppRouter } from "@upstash/qstash/nextjs";

export const POST = verifySignatureAppRouter(
  async (req) => {
    const body = await req.json();
    return Response.json({ received: true });
  },
  {
    currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,
    nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY,
    clockTolerance: 5, // Allow 5 seconds clock difference
  }
);

Multi-Region Support

import { verifySignatureAppRouter } from "@upstash/qstash/nextjs";

export const POST = verifySignatureAppRouter(async (req) => {
  const upstashRegion = req.headers.get("upstash-region");
  console.log("Request from region:", upstashRegion);

  const body = await req.json();
  return Response.json({ region: upstashRegion, data: body });
});

Pages Router Verification

Using verifySignature

For Pages Router API routes, use the verifySignature wrapper:

import type { NextApiRequest, NextApiResponse } from "next";
import { verifySignature } from "@upstash/qstash/nextjs";

// pages/api/webhook.ts
async function handler(req: NextApiRequest, res: NextApiResponse) {
  const body = req.body;

  // Request is verified
  console.log("Received:", body);

  res.status(200).json({ success: true });
}

export default verifySignature(handler);

With Configuration

import type { NextApiRequest, NextApiResponse } from "next";
import { verifySignature } from "@upstash/qstash/nextjs";

async function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ message: "Verified" });
}

export default verifySignature(handler, {
  currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,
  nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY,
  clockTolerance: 5,
});

Manual Verification with Receiver

For more control, use the Receiver class directly:

Manual Verification

import { Receiver } from "@upstash/qstash";
import { NextRequest, NextResponse } from "next/server";

const receiver = new Receiver({
  currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY!,
  nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY!,
});

export async function POST(req: NextRequest) {
  const signature = req.headers.get("upstash-signature");

  if (!signature) {
    return NextResponse.json({ error: "Missing signature" }, { status: 401 });
  }

  const body = await req.text();

  try {
    await receiver.verify({
      signature,
      body,
      url: req.url,
    });

    // Verified - parse and process
    const data = JSON.parse(body);
    return NextResponse.json({ success: true });
  } catch (error) {
    return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
  }
}

Best Practices

Handle Errors Gracefully

export const POST = verifySignatureAppRouter(async (req) => {
  try {
    const body = await req.json();
    await processWebhook(body);
    return Response.json({ success: true });
  } catch (error) {
    console.error("Processing error:", error);
    return Response.json({ error: "Processing failed" }, { status: 500 });
  }
});

Common Issues

Missing Environment Variables

if (!process.env.QSTASH_CURRENT_SIGNING_KEY) {
  throw new Error("Missing QSTASH_CURRENT_SIGNING_KEY");
}

Related Resources

Source: SKILL.md on GitHub

No alerts17d3 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides comprehensive documentation and implementation guides for the Upstash QStash JS SDK. It includes a local development feature that automatically downloads and executes the official QStash CLI binary. While this involves remote code download and execution, it originates from the trusted vendor. The skill also processes external webhooks, creating a surface for indirect prompt injection, which is mitigated by built-in signature verification instructions.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

Signed by skilld at 36daab8. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 5 days ago.

Activeupdated last month
metadata
{
  "author": "Upstash",
  "homepage": "https://upstash.com"
}

README badge

README badge for upstash/skills/upstash-qstash-js