← Files Upstash RedisARCHIVED FILE
skills/upstash-qstash-js/fundamentals/url-groups.md
2.98 KB · Oct 5, 2026 · 18:18 UTC
# URL Groups
URL Groups (also called Topics) let you publish a single message to multiple endpoints simultaneously.
## Creating URL Groups
Add endpoints to create or update a URL group:
```typescript
import { Client } from "@upstash/qstash";
const client = new Client({ token: process.env.QSTASH_TOKEN! });
await client.urlGroups().addEndpoints({
name: "payment-webhooks",
endpoints: [
{ url: "https://api1.example.com/webhook" },
{ url: "https://api2.example.com/webhook" },
{ url: "https://api3.example.com/webhook", name: "primary" },
],
});
```
- `name`: URL group identifier (alphanumeric, hyphens, underscores, periods)
- `url`: Endpoint URL (required)
- `name`: Optional endpoint name for identification
## Publishing to URL Groups
Publish once, deliver to all endpoints:
```typescript
const result = await client.publishJSON({
urlGroup: "payment-webhooks",
body: { orderId: "123", amount: 99.99, status: "paid" },
});
// Returns array with result for each endpoint
result.forEach((r) => {
console.log(`Sent to ${r.url}: ${r.messageId}`);
});
```
Each endpoint gets a separate message with its own retry logic and tracking.
## Managing Endpoints
### Remove Endpoints
Remove by URL or name:
```typescript
// Remove by URL
await client.urlGroups().removeEndpoints({
name: "payment-webhooks",
endpoints: [{ url: "https://api2.example.com/webhook" }],
});
// Remove by endpoint name
await client.urlGroups().removeEndpoints({
name: "payment-webhooks",
endpoints: [{ name: "primary" }],
});
```
### List URL Groups
```typescript
const groups = await client.urlGroups().list();
groups.forEach((group) => {
console.log(`${group.name}: ${group.endpoints.length} endpoints`);
group.endpoints.forEach((ep) => {
console.log(` - ${ep.url}${ep.name ? ` (${ep.name})` : ""}`);
});
});
```
### Get Specific URL Group
```typescript
const group = await client.urlGroups().get("payment-webhooks");
console.log(`Created: ${new Date(group.createdAt)}`);
console.log(`Updated: ${new Date(group.updatedAt)}`);
console.log(`Endpoints: ${group.endpoints.length}`);
```
### Delete URL Group
```typescript
await client.urlGroups().delete("payment-webhooks");
```
Deleting a URL group does not affect in-flight messages.
## URL Group vs Individual Publishing
**Use URL Groups when:**
- Broadcasting same message to multiple endpoints
- Need to manage endpoint list centrally
- Adding/removing endpoints dynamically
- All endpoints process the same data
**Use individual publishing when:**
- Each endpoint needs different message content
- Different retry/timeout settings per endpoint
- Endpoints have different purposes
## All Message Options Work
URL Groups support all publishing options:
```typescript
await client.publishJSON({
urlGroup: "notifications",
body: { event: "user.signup", userId: "123" },
delay: 60,
retries: 5,
callback: "https://api.example.com/callback",
deduplicationId: "signup-123",
});
```
See [Publishing Messages](publishing-messages.md) for all options.
SHA-256: 2f52a6b398def7adafd378db60ed6b60a4f7dc69a8564a9d2269fd3db524cb4c