Usage
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: "<UPSTASH_REDIS_URL>",
token: "<UPSTASH_REDIS_TOKEN>",
});
const length = await redis.xlen("events");
Parameters
Response
The number of entries in the stream.Returns 0 if the key doesn’t exist or is an empty stream.
Examples
Get stream length
// Add some entries
await redis.xadd("events", "*", { user: "alice", action: "login" });
await redis.xadd("events", "*", { user: "bob", action: "logout" });
await redis.xadd("events", "*", { user: "charlie", action: "update" });
// Get the length
const length = await redis.xlen("events");
console.log(length); // 3
Check if stream exists
const length = await redis.xlen("nonexistent");
if (length === 0) {
console.log("Stream doesn't exist or is empty");
} else {
console.log(`Stream has ${length} entries`);
}
Monitor stream growth
const before = await redis.xlen("events");
// Add new entries
await redis.xadd("events", "*", { new: "entry1" });
await redis.xadd("events", "*", { new: "entry2" });
const after = await redis.xlen("events");
const added = after - before;
console.log(`Added ${added} new entries`);
// Output: Added 2 new entries
Track stream size with trimming
// Add 1000 entries
for (let i = 0; i < 1000; i++) {
await redis.xadd("events", "*", { index: i });
}
console.log(await redis.xlen("events")); // 1000
// Add new entry with trimming to max 500
await redis.xadd(
"events",
"*",
{ index: 1000 },
{
trim: {
type: "MAXLEN",
comparison: "~",
threshold: 500
}
}
);
console.log(await redis.xlen("events")); // ~500 (approximate due to "~")
Check multiple streams
const streams = ["stream1", "stream2", "stream3"];
const lengths = await Promise.all(
streams.map(stream => redis.xlen(stream))
);
streams.forEach((stream, i) => {
console.log(`${stream}: ${lengths[i]} entries`);
});
// Output:
// stream1: 10 entries
// stream2: 25 entries
// stream3: 0 entries
Stream capacity check
const MAX_STREAM_SIZE = 10000;
const currentSize = await redis.xlen("events");
const remainingCapacity = MAX_STREAM_SIZE - currentSize;
if (remainingCapacity > 0) {
console.log(`Can add ${remainingCapacity} more entries`);
await redis.xadd("events", "*", { data: "new entry" });
} else {
console.log("Stream is at capacity, trimming required");
await redis.xadd(
"events",
"*",
{ data: "new entry" },
{ trim: { type: "MAXLEN", comparison: "=", threshold: MAX_STREAM_SIZE } }
);
}
Compare stream sizes
const activeLength = await redis.xlen("active-events");
const archivedLength = await redis.xlen("archived-events");
console.log(`Active: ${activeLength}, Archived: ${archivedLength}`);
console.log(`Total events processed: ${activeLength + archivedLength}`);
Conditional operations based on size
async function addEntry(key: string, data: Record<string, unknown>) {
const length = await redis.xlen(key);
// If stream is getting large, use approximate trimming
const trimOptions = length > 5000 ? {
trim: {
type: "MAXLEN" as const,
comparison: "~" as const,
threshold: 5000
}
} : undefined;
return await redis.xadd(key, "*", data, trimOptions);
}
await addEntry("events", { user: "alice", action: "click" });
Calculate stream growth rate
const initialLength = await redis.xlen("metrics");
// Wait 1 minute
await new Promise(resolve => setTimeout(resolve, 60000));
const finalLength = await redis.xlen("metrics");
const entriesPerMinute = finalLength - initialLength;
console.log(`Stream growth rate: ${entriesPerMinute} entries/minute`);
Important Notes
Empty Streams
XLEN returns 0 for both non-existent keys and empty streams:
// Non-existent stream
const len1 = await redis.xlen("never-created");
console.log(len1); // 0
// Empty stream (all entries deleted)
await redis.xadd("temp", "*", { data: "test" });
await redis.del("temp");
const len2 = await redis.xlen("temp");
console.log(len2); // 0
To distinguish between them:
const exists = await redis.exists("events");
const length = await redis.xlen("events");
if (!exists) {
console.log("Stream doesn't exist");
} else if (length === 0) {
console.log("Stream exists but is empty");
} else {
console.log(`Stream has ${length} entries`);
}
- XLEN is an O(1) operation (constant time)
- Very fast even for streams with millions of entries
- Safe to call frequently for monitoring
After Trimming
XLEN reflects the current number of entries after any trimming:
await redis.xadd("events", "*", { data: "1" });
await redis.xadd("events", "*", { data: "2" });
await redis.xadd("events", "*", { data: "3" });
console.log(await redis.xlen("events")); // 3
// Add with exact trim to 2 entries
await redis.xadd(
"events",
"*",
{ data: "4" },
{ trim: { type: "MAXLEN", comparison: "=", threshold: 2 } }
);
console.log(await redis.xlen("events")); // 2
Use Cases
- Monitoring: Track stream size over time
- Capacity planning: Check if trimming is needed
- Metrics: Calculate processing rates
- Validation: Verify entries were added successfully
- Debugging: Understand stream state