# How to Collect Telegram Media Groups in Node.js

> Source: <https://dev.to/nikitosit/how-to-collect-telegram-media-groups-in-nodejs-d8c>
> Published: 2026-05-22 20:12:52+00:00

When working with the Telegram Bot API, it is easy to expect that an album with multiple photos will arrive as a single event.

But Telegram works differently.

If a user sends an album of 3 photos, your bot doesn't receive one "post" object. Instead, it receives 3 separate updates in rapid succession:

``` php
Update #1 -> photo_1
Update #2 -> photo_2
Update #3 -> photo_3

instead of:

single_post -> [photo_1, photo_2, photo_3]
```

The Headache: Why this is hard

Handling these updates manually forces you to deal with a lot of "plumbing" code that has nothing to do with your actual bot logic:

Duplicate database records: Accidentally creating 3 posts instead of 1.

Race conditions: Multiple updates hitting your server at the exact same time.

Buffering & Timeouts: Deciding how long to wait for the "next" photo before assuming the group is complete.

Ordering: Ensuring the photos stay in the order the user intended.

Typical "infrastructure" code usually starts looking like this mess:

``` js
const mediaGroups = new Map();
// buffering logic...
// sorting logic...
// duplicate prevention...
// cleanup jobs...
// timeout handling...
```

At some point, you realize you are rewriting low-level infrastructure instead of building your actual features.

The Solution: telegram-media

I built telegram-media—a lightweight TypeScript library for Node.js that collects these scattered Telegram updates into a single, normalized object.

**Installation**

```
npm install telegram-media
```

**Usage Example**

Here is how you can use it to collect media and save it to a database (like Prisma) using a Redis storage backend:

``` js
const collector = createTelegramMediaGroup({
  async onCollected(post) {
    // This only fires ONCE per media group
    await prisma.telegramPost.create({
      data: mapCollectedPostToPrismaInput(post),
    });
  },

  // Use Redis for distributed environments
  storage: createRedisMediaGroupStorage(redisClient),

  timeoutMs: 3000,

  supportedMediaTypes: ["photo", "video", "audio"],
});
```

**Why I Built This?**

I ran into this problem while building a Telegram ingestion system for a personal project. At first, the logic seemed simple—just a small Set and a setTimeout.

Then the edge cases hit: distributed workers fighting over the same group, incomplete groups caused by network lag, and Redis synchronization issues. I extracted the logic into a standalone package so no one else has to solve this from scratch.

**Key Features**

-
**Media Group Aggregation**— Automatically groups related Telegram updates into a single normalized post. -
**Redis Support**— Ready for production and distributed environments. -
**Duplicate Prevention**— Handles Telegram retry updates safely. -
**Ordering**— Preserves the original media sequence. -
**TypeScript**— Fully typed for a better developer experience.

**Explore**

**What do you think?**

I'd love to hear how others are handling media groups. Do you use a custom buffer, or do you just process each image individually and update the record as you go?

Let me know in the comments!
