DEV Community

Cover image for Building a Production-Style AI Telegram Bot with Node.js, Gemini, Cron and Fallbacks
Soumyajit Mukherjee
Soumyajit Mukherjee

Posted on

Building a Production-Style AI Telegram Bot with Node.js, Gemini, Cron and Fallbacks

I wanted to build a small AI project that was more than:

prompt → LLM → response
Enter fullscreen mode Exit fullscreen mode

So I built an AI-powered Telegram motivation bot using Node.js, Google Gemini and the Telegram Bot API.

The interesting part isn't the motivational content itself.

The interesting part is everything around the AI model:

  • Scheduling
  • Personalization
  • Persistent user state
  • Streaks
  • Feedback
  • Telemetry
  • Retry logic
  • Model fallback
  • Caching
  • Local fallback content
  • Protected webhooks

This article breaks down the architecture.

Tech Stack

The core stack is:

Node.js
Express.js
Telegram Bot API
Google Gemini
node-cron
dotenv
Jest
Enter fullscreen mode Exit fullscreen mode

The project uses ES modules and keeps the application separated into components such as bot commands, actions, services, data management and configuration.

High-Level Architecture

The system roughly looks like this:

                    ┌─────────────────┐
                    │ Telegram User   │
                    └────────┬────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │ Telegram Bot    │
                    │ Command Layer   │
                    └────────┬────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │ Motivation      │
                    │ Generation      │
                    │ Service         │
                    └────────┬────────┘
                             │
                    ┌────────┴────────┐
                    ▼                 ▼
              ┌──────────┐      ┌───────────┐
              │ Gemini   │      │ Fallback  │
              │ API      │      │ System    │
              └──────────┘      └───────────┘
                    │
                    ▼
              ┌────────────┐
              │ Telemetry  │
              └────────────┘
Enter fullscreen mode Exit fullscreen mode

1. Telegram Command Layer

The bot exposes multiple commands.

Some of the main ones are:

/motivate
/today
/history
/stats
/leaderboard
/settings
/subscribe
/unsubscribe
/schedule
/set_tone
/set_language
/suggest_quote_topic
Enter fullscreen mode Exit fullscreen mode

For example:

/motivate
Enter fullscreen mode Exit fullscreen mode

generates an on-demand motivational message.

A user can also request a topic-specific message:

/suggest_quote_topic job interviews
Enter fullscreen mode Exit fullscreen mode

The command layer initializes the user, invokes the generation service and stores the resulting data.

2. AI Generation Service

The main generation logic lives in the motivation/brain service.

The service uses the Google Generative AI SDK.

One interesting design decision is the use of multiple persona archetypes.

const personas = {
    stoic: "...",
    warrior: "...",
    philosopher: "...",
    strategist: "...",
    mentor: "...",
    elder: "...",
    survivor: "...",
    observer: "...",
    wanderer: "..."
};
Enter fullscreen mode Exit fullscreen mode

If the user selects a mixed/random mode, the application can choose an archetype dynamically.

3. Multiple Generation Modalities

The application also varies how the generated message should be expressed.

The current modalities include:

RAW_REALITY
DEEP_OBSERVATION
QUIET_COMPASSION
PRAGMATIC
Enter fullscreen mode Exit fullscreen mode

This is useful because prompt variation doesn't necessarily require completely different application architectures.

A small controlled set of generation dimensions can create considerably more variety.

4. Output Constraints

The prompt also places constraints on the generated content.

For example, the generation service asks the model for:

  • A short response
  • A complete standalone sentence
  • No unnecessary formatting
  • No generic AI clichés
  • A grounded tone

The application then trims and validates the model output before returning it.

5. Retry and Model Fallback

This is one of the parts I found most useful from an engineering perspective.

The application maintains a model priority chain.

Conceptually:

const MODEL_PRIORITY_CHAIN = [
    "primary-model",
    "fallback-model"
];
Enter fullscreen mode Exit fullscreen mode

The generation function loops through the configured models and retries failures.

It also detects certain model availability/deprecation errors and can move to the next model.

This is important because AI providers change models over time.

Hard-coding one model and assuming it will always exist isn't a great long-term strategy.

6. Memory Cache

The generation service also keeps a temporary in-memory cache.

The cache is keyed around parameters such as:

language
tone
schedule
A/B variant
Enter fullscreen mode Exit fullscreen mode

This means the application has another way to avoid unnecessary AI calls when an appropriate recent response already exists.

The cache also becomes useful when dealing with API rate limits or temporary upstream failures.

7. Local Fallback

What happens if the AI system fails completely?

The application can retrieve fallback content from local data.

The conceptual hierarchy is:

Gemini
   ↓
Retry
   ↓
Model fallback
   ↓
Memory cache
   ↓
Local fallback
Enter fullscreen mode Exit fullscreen mode

This is a useful pattern for any application that depends on an external API.

A graceful degradation strategy is usually better than returning an error every time an external service has a problem.

8. Automated Scheduling

The bot uses node-cron.

The current schedules include:

cron.schedule('0 8 * * *', ...)
cron.schedule('0 13 * * *', ...)
cron.schedule('0 18 * * *', ...)
cron.schedule('0 19 * * 0', ...)
Enter fullscreen mode Exit fullscreen mode

These correspond to:

08:00 → Morning
13:00 → Midday
18:00 → Evening
Sunday 19:00 → Weekly
Enter fullscreen mode Exit fullscreen mode

The schedules use:

Asia/Kolkata
Enter fullscreen mode Exit fullscreen mode

as the timezone.

The application also has an automated cleanup job.

9. Per-User Scheduling

The cron system doesn't simply broadcast every message to everyone.

It checks each user's schedule configuration.

For example:

user.schedule[scheduleType] === true
Enter fullscreen mode Exit fullscreen mode

Only users who have enabled a particular dispatch period are targeted.

That creates an important separation:

Global Scheduler
       ↓
User Preferences
       ↓
Eligible Subscribers
       ↓
AI Generation
       ↓
Telegram Delivery
Enter fullscreen mode Exit fullscreen mode

10. Streak Tracking

After successful dispatch, the user's streak is updated.

The project also has milestone badges.

For example:

3 days   → Rising Star
7 days   → 7-Day Believer
14 days  → Unbreakable
30 days  → Iron Will
100 days → Century Member
Enter fullscreen mode Exit fullscreen mode

This turns a simple messaging bot into a stateful application.

11. Feedback Buttons

Generated messages contain inline Telegram buttons:

👍    👎
Enter fullscreen mode Exit fullscreen mode

The callback handler determines whether the user voted up or down.

The application then records:

chat ID
quote
vote
A/B variant
Enter fullscreen mode Exit fullscreen mode

The buttons are subsequently removed to prevent repeated submissions for the same message.

This is a small feature, but it introduces an important concept:

AI output can be treated as an experiment rather than an immutable result.

12. A/B Variant

The project also has an A/B mechanism.

The user's chat ID is used to determine the variant.

One variant receives an additional generation instruction.

This creates a simple way to compare different prompting strategies.

In a more advanced implementation, this could be replaced with a proper experiment assignment system.

13. Telemetry

The application records telemetry around generated messages.

Some tracked information includes:

event
chatId
schedulePeriod
quoteText
source
responseTimeMs
apiSuccess
Enter fullscreen mode Exit fullscreen mode

This makes it possible to answer questions such as:

  • How long is AI generation taking?
  • How often is the API succeeding?
  • How frequently is fallback content being used?
  • Which scheduling period generated an event?
  • Which model produced the response?

Without telemetry, these questions are much harder to answer.

14. Express API

The application also starts an Express server.

One endpoint exposes recent generated quotes:

GET /api/quotes/latest
Enter fullscreen mode Exit fullscreen mode

There is also a protected broadcast endpoint:

POST /api/webhook/broadcast
Enter fullscreen mode Exit fullscreen mode

The broadcast endpoint checks an API key supplied through a request header.

It can then initiate a broadcast to active users.

This creates an integration point for external systems.

15. Environment Variables

Secrets are kept outside the source code.

The application expects configuration such as:

PORT
TELEGRAM_BOT_API_TOKEN
GEMINI_API_KEY
TELEGRAM_CHAT_ID
WEBHOOK_SECRET
IS_TEST_MODE
Enter fullscreen mode Exit fullscreen mode

This is particularly important for Telegram and AI projects because both bot tokens and API keys should never be committed to a public repository.

16. Local Test Mode

The application also has a test mode.

Instead of waiting for the scheduled cron execution, the system can execute the dispatch logic immediately.

That makes local development much easier.

A scheduled system without a test path can become frustrating to debug.

17. Why This Project Is More Than an AI Demo

The project started with a very simple feature:

Generate a motivational message.

But the resulting architecture looks more like:

             ┌───────────────┐
             │ Telegram      │
             └───────┬───────┘
                     │
             ┌───────▼───────┐
             │ Commands      │
             └───────┬───────┘
                     │
          ┌──────────▼──────────┐
          │ User State          │
          │ Preferences         │
          │ Schedule            │
          │ Streak              │
          └──────────┬──────────┘
                     │
             ┌───────▼───────┐
             │ AI Engine     │
             └───────┬───────┘
                     │
       ┌─────────────┼─────────────┐
       ▼             ▼             ▼
    Gemini        Cache        Fallback
       │             │             │
       └─────────────┼─────────────┘
                     ▼
                Telemetry
                     │
                     ▼
              Feedback Loop
Enter fullscreen mode Exit fullscreen mode

And that's what makes the project useful as a learning exercise.

Lessons From Building It

The biggest lesson was that:

Calling an LLM is the easy part.

The engineering challenges appear around it.

You need to think about:

  • Reliability
  • Rate limits
  • Model retirement
  • Caching
  • User state
  • Scheduling
  • Feedback
  • Observability
  • Security
  • Testing
  • Graceful degradation

Those problems are not unique to motivational bots.

They appear in many AI applications.

Possible Improvements

If I continued developing this project, I'd consider adding:

  • Redis for distributed caching
  • PostgreSQL or MongoDB for persistent production storage
  • Docker
  • More comprehensive automated tests
  • Structured logging
  • Metrics dashboards
  • More sophisticated experimentation
  • User-specific scheduling/timezones
  • Better analytics
  • Additional messaging integrations

Conclusion

This project started as a small Telegram automation idea.

It ended up becoming an interesting exercise in combining:

Node.js + Telegram + Gemini + automation + state + telemetry + reliability.

If you're learning AI application development, don't stop at:

const result = await model.generateContent(prompt);
Enter fullscreen mode Exit fullscreen mode

Ask what happens before and after that line.

That's where most of the interesting engineering begins.

Source Code

The complete project is available here:

https://github.com/starJeet000/Telegram-Daily-Motivation-Bot

If you build something similar, I'd be interested in seeing how you handle AI reliability, caching and feedback.

Top comments (0)