Best Practices
Production-ready patterns for building bots.
Follow these best practices to build robust, maintainable bots that scale well and provide excellent user experiences. These practices cover security, performance, code organization, and production operations—all essential aspects of building production-ready bots. Understanding and applying these practices helps you avoid common pitfalls and build bots that are reliable, secure, and easy to maintain.
Whether you're building your first bot or scaling to thousands of users, these practices provide a solid foundation for building bots that work well in production environments.
Security
Security is critical for production bots—they handle user data, interact with external APIs, and are exposed to the internet. Following security best practices protects your bot from attacks, prevents data leaks, and ensures your bot operates safely. Security should be considered from the start, not added as an afterthought.
Error Handling
Proper error handling ensures your bot continues functioning even when things go wrong. Errors are inevitable in production—network issues, API failures, invalid input, and unexpected conditions all cause errors. Good error handling catches these errors, logs them appropriately, and provides helpful feedback to users without crashing your bot.
Error handling should be comprehensive but not intrusive. Catch errors at appropriate levels, log them with context, and provide user-friendly feedback. Don't let errors break your bot's functionality or expose sensitive information to users.
Performance
Bot performance directly impacts user experience—slow bots feel unresponsive and frustrate users. Optimizing performance involves keeping middleware fast, caching expensive operations, and avoiding unnecessary work. Performance optimization is especially important for bots that handle high message volumes or make external API calls.
Good performance practices ensure your bot responds quickly even under load. Fast middleware, efficient caching, and optimized database queries all contribute to a responsive bot experience.
Code Organization
Well-organized code is easier to maintain, test, and extend. Organizing your bot code into logical modules—separate files for commands, middleware, and utilities—makes your codebase more manageable as it grows. Good organization follows the single responsibility principle, keeping related code together and making dependencies clear.
Organized code is easier to work with, especially as your bot grows and you add more features. Clear structure helps new developers understand the codebase and makes refactoring safer.
Documentation
Good documentation helps developers understand your bot's functionality and use it correctly. Documenting commands, middleware, and complex logic makes your codebase more maintainable and helps new team members get up to speed quickly. Well-documented code is easier to debug, extend, and refactor.
Documentation should be clear, concise, and focused on helping developers understand how to use your bot effectively. Include examples, explain edge cases, and document any assumptions or limitations.
Monitoring
Monitoring your bot in production helps you understand how it performs, identify issues before they become critical, and track important metrics. Good monitoring includes logging important events, tracking performance metrics, and setting up alerts for errors or anomalies. Monitoring is essential for maintaining production bots and ensuring they operate reliably.
Effective monitoring gives you visibility into your bot's behavior and helps you make data-driven decisions about improvements and optimizations.
Testing
Comprehensive testing ensures your bot works correctly before reaching production. Tests catch bugs early, give you confidence when refactoring, and document expected behavior. Writing tests for commands, middleware, and error handling helps you build reliable bots that work as expected.
Good tests are fast, reliable, and test actual behavior rather than implementation details. Focus on testing what matters—user-facing behavior and critical business logic.
Complete Example
Here's a complete example that brings together multiple best practices into a production-ready bot. This example demonstrates security (environment variables, webhook validation), error handling (global error handlers), performance (fast middleware), code organization (separate commands), and monitoring (structured logging). It shows how all these practices work together to create a robust, maintainable bot.
This example demonstrates:
- Security: Using environment variables and webhook validation
- Error Handling: Comprehensive error handling at multiple levels
- Performance: Fast middleware and efficient caching
- Code Organization: Separated commands and reusable middleware
- Monitoring: Structured logging and metrics tracking
import { Bot, telegram } from '@igniter-js/bot'
import { authMiddleware } from './middleware/auth'
import { loggingMiddleware } from './middleware/logging'
import { rateLimitMiddleware } from './middleware/rate-limit'
import { weatherCommand } from './commands/weather'
import { newsCommand } from './commands/news'
import pino from 'pino'
const logger = pino({
level: process.env.LOG_LEVEL || 'info'
})
const bot = Bot.create({
id: 'production-bot',
name: 'Production Bot',
logger: {
debug: logger.debug.bind(logger),
info: logger.info.bind(logger),
warn: logger.warn.bind(logger),
error: logger.error.bind(logger)
},
adapters: {
telegram: telegram({
token: process.env.TELEGRAM_TOKEN!,
handle: '@production_bot',
webhook: {
url: process.env.TELEGRAM_WEBHOOK_URL!,
secret: process.env.TELEGRAM_SECRET // Webhook validation
}
})
},
middlewares: [
loggingMiddleware,
rateLimitMiddleware,
authMiddleware
],
commands: {
weather: weatherCommand,
news: newsCommand
}
})
// Global error handler
bot.on('error', async (ctx) => {
// @ts-expect-error
const err = ctx.error
logger.error({
code: err.code,
message: err.message,
userId: ctx.message.author.id
}, 'Bot error')
await ctx.bot.send({
provider: ctx.provider,
channel: ctx.channel.id,
content: {
type: 'text',
content: '❌ An error occurred. Please try again later.'
}
})
})
await bot.start()