Why your bot needs a database

Without persistent storage, your bot forgets everything when it restarts. Warning counts reset, custom settings disappear, and user preferences vanish. A database gives your bot memory that survives restarts, crashes, and redeployments.

The right database depends on your bot's complexity, your hosting environment, and how much data you need to store. This guide covers every practical option from the simplest to the most scalable.

Database comparison

DatabaseTypeHosting requiredBest forFree tier
JSON filesFile-basedNone (local files)Very small bots, prototypingN/A
SQLiteEmbedded SQLNone (local file)Small to medium botsN/A
MongoDB AtlasDocument (cloud)Cloud hostedFlexible schemas, rapid development512 MB free
PostgreSQLRelational (cloud/VPS)Self-hosted or cloudComplex queries, data integrityVarious free tiers
SupabasePostgreSQL (managed)Cloud hostedPostgreSQL without server management500 MB free
PlanetScaleMySQL (managed)Cloud hostedMySQL with branching workflow5 GB free
RedisIn-memory key-valueSelf-hosted or cloudCaching, session data, rate limitingVarious free tiers

JSON file storage

The simplest approach: read and write JSON files. No dependencies, no setup, works everywhere.

// Node.js - simple JSON storage
const fs = require('fs');
const DATA_FILE = './data/warnings.json';

function loadData() {
    try {
        return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
    } catch {
        return {};
    }
}

function saveData(data) {
    fs.mkdirSync('./data', { recursive: true });
    fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2));
}

Limitations: JSON files do not handle concurrent writes safely. If two commands try to write at the same time, data can be corrupted. They also load the entire dataset into memory, which becomes slow with large files. Use JSON only for bots with minimal data storage needs.

On MonkeyBytes, JSON files work perfectly because storage is persistent. On platforms with ephemeral storage like Heroku or Railway, your JSON files reset on every deployment.

SQLite

SQLite is the best option for most Discord bots. It stores data in a single file, requires no external server, supports SQL queries, and handles concurrent reads safely. It is the database of choice for bots on MonkeyBytes and other platforms with persistent storage.

Node.js with better-sqlite3

npm install better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('./data/bot.db');

// Create tables
db.exec(`
    CREATE TABLE IF NOT EXISTS warnings (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id TEXT NOT NULL,
        guild_id TEXT NOT NULL,
        reason TEXT,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
`);

// Insert a warning
const insert = db.prepare('INSERT INTO warnings (user_id, guild_id, reason) VALUES (?, ?, ?)');
insert.run('123456789', '987654321', 'Spamming in general');

// Query warnings
const warnings = db.prepare('SELECT * FROM warnings WHERE user_id = ?').all('123456789');

Python with aiosqlite

pip install aiosqlite
import aiosqlite

async def setup_db():
    async with aiosqlite.connect('./data/bot.db') as db:
        await db.execute('''
            CREATE TABLE IF NOT EXISTS warnings (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id TEXT NOT NULL,
                guild_id TEXT NOT NULL,
                reason TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        await db.commit()

async def add_warning(user_id, guild_id, reason):
    async with aiosqlite.connect('./data/bot.db') as db:
        await db.execute(
            'INSERT INTO warnings (user_id, guild_id, reason) VALUES (?, ?, ?)',
            (user_id, guild_id, reason)
        )
        await db.commit()

SQLite on MonkeyBytes: Works out of the box. The database file is stored in your persistent 1 GB SSD storage and survives restarts and redeployments. Upload your bot with an empty database, and it creates the file automatically on first run.

MongoDB Atlas

MongoDB is a document database that stores data as JSON-like documents. MongoDB Atlas provides a free cloud-hosted cluster with 512 MB of storage, which is enough for most Discord bots.

The key advantage of MongoDB for Discord bots is schema flexibility. You can store different data structures in the same collection without defining a rigid schema upfront. This is useful for bots that store varied user data or configuration.

Node.js with Mongoose

npm install mongoose
const mongoose = require('mongoose');

// Connect using environment variable
mongoose.connect(process.env.MONGODB_URI);

// Define a schema
const warningSchema = new mongoose.Schema({
    userId: String,
    guildId: String,
    reason: String,
    createdAt: { type: Date, default: Date.now }
});

const Warning = mongoose.model('Warning', warningSchema);

// Create a warning
await Warning.create({ userId: '123', guildId: '456', reason: 'Spamming' });

// Query warnings
const warnings = await Warning.find({ userId: '123' });

Store your MongoDB connection string in an environment variable. See our environment variables guide for setup.

PostgreSQL

PostgreSQL is the most powerful option for Discord bots that need complex queries, data relationships, and strict data integrity. It requires either a VPS to self-host or a cloud provider.

Free PostgreSQL hosting options include Supabase (500 MB), Neon (512 MB), and ElephantSQL (20 MB). For most bots, Supabase's free tier provides enough storage.

Choosing the right database

Use JSON files if

  • Your bot stores minimal data (a few settings per guild)
  • You are prototyping and will migrate to a database later
  • You do not want any dependencies

Use SQLite if

  • Your bot needs reliable persistent storage
  • You host on a platform with persistent file storage (MonkeyBytes, VPS)
  • You want SQL query capabilities without external services
  • Your dataset is under 1 GB

Use MongoDB Atlas if

  • You host on a platform with ephemeral storage (Heroku, Railway)
  • Your data structure is flexible and evolving
  • You prefer a document model over SQL tables

Use PostgreSQL if

  • Your bot needs complex queries with joins and aggregations
  • Data integrity and consistency are critical
  • Your bot handles financial data, permissions, or audit logs

Database security

  • Never expose connection strings in code. Use environment variables for all database credentials.
  • Use parameterised queries. Never concatenate user input into SQL strings. Always use prepared statements or parameterised queries to prevent SQL injection.
  • Restrict network access. For cloud databases, whitelist only the IP addresses that need access.
  • Back up regularly. SQLite databases can be backed up by copying the file. Cloud databases typically have automated backup options.

For comprehensive security practices, read our security guide.

Ready to deploy your bot with a database? See our getting started guide for deployment instructions, or read the Node.js or Python deployment guides for language-specific setup. For scaling your database as your bot grows, check our scaling guide.

GuideComplete Hosting Guide GuideNode.js Deployment GuidePython Deployment GuideScaling Your Bot