Black Friday: first month free on quarterly plans · until 30 Nov See the plans Conditions
New here? Try a Minecraft server or Discord bot free for 24 hours. Try free
ServerSparkServerSpark

Knowledge base

Discord bot with a database (SQLite) and buttons

A working example in discord.js and discord.py: store data in SQLite and let users click buttons.

NVMe nodesNightly backupsOnline in minutes

Updated 25 October 2026

A bot gets really useful when it remembers things (points, settings, warnings) and gives users buttons to click. This guide builds a small working example with a SQLite database and a button, in JavaScript (discord.js) and in Python (discord.py). SQLite is a database in a single file: no separate database server needed.

What the example does

The command /button shows a button. Every click is counted per user in the database, and the bot replies with the user's total. The count survives restarts because it's stored in the file data.db.

JavaScript (discord.js)

package.json needs these packages (they are installed automatically when your bot starts):

{
  "dependencies": {
    "discord.js": "^14.16.0",
    "better-sqlite3": "^11.0.0",
    "dotenv": "^16.4.0"
  }
}

index.js:

require('dotenv').config();
const { Client, GatewayIntentBits, Events, ActionRowBuilder, ButtonBuilder, ButtonStyle, MessageFlags } = require('discord.js');
const Database = require('better-sqlite3');

const db = new Database('data.db');
db.prepare('CREATE TABLE IF NOT EXISTS clicks (user_id TEXT PRIMARY KEY, count INTEGER NOT NULL DEFAULT 0)').run();

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, async (c) => {
  await c.application.commands.create({ name: 'button', description: 'Show a button' });
  console.log(`Logged in as ${c.user.tag}`);
});

client.on(Events.InteractionCreate, async (interaction) => {
  if (interaction.isChatInputCommand() && interaction.commandName === 'button') {
    const row = new ActionRowBuilder().addComponents(
      new ButtonBuilder().setCustomId('click').setLabel('Click me').setStyle(ButtonStyle.Primary));
    await interaction.reply({ content: 'Press the button:', components: [row] });
  }
  if (interaction.isButton() && interaction.customId === 'click') {
    db.prepare('INSERT INTO clicks (user_id, count) VALUES (?, 1) ON CONFLICT(user_id) DO UPDATE SET count = count + 1').run(interaction.user.id);
    const { count } = db.prepare('SELECT count FROM clicks WHERE user_id = ?').get(interaction.user.id);
    await interaction.reply({ content: `You clicked ${count} times.`, flags: MessageFlags.Ephemeral });
  }
});

client.login(process.env.DISCORD_TOKEN);

Python (discord.py)

requirements.txt (SQLite is built into Python):

discord.py
python-dotenv

app.py:

import os
import sqlite3

import discord
from discord import app_commands
from dotenv import load_dotenv

load_dotenv()
db = sqlite3.connect("data.db")
db.execute("CREATE TABLE IF NOT EXISTS clicks (user_id INTEGER PRIMARY KEY, count INTEGER NOT NULL DEFAULT 0)")
db.commit()


class Clicker(discord.ui.View):
    def __init__(self):
        super().__init__(timeout=None)  # the button keeps working, also after a restart

    @discord.ui.button(label="Click me", style=discord.ButtonStyle.primary, custom_id="click")
    async def click(self, interaction: discord.Interaction, button: discord.ui.Button):
        db.execute("INSERT INTO clicks (user_id, count) VALUES (?, 1) "
                   "ON CONFLICT(user_id) DO UPDATE SET count = count + 1", (interaction.user.id,))
        db.commit()
        (count,) = db.execute("SELECT count FROM clicks WHERE user_id = ?", (interaction.user.id,)).fetchone()
        await interaction.response.send_message(f"You clicked {count} times.", ephemeral=True)


class Bot(discord.Client):
    def __init__(self):
        super().__init__(intents=discord.Intents.default())
        self.tree = app_commands.CommandTree(self)

    async def setup_hook(self):
        self.add_view(Clicker())
        await self.tree.sync()


bot = Bot()


@bot.tree.command(description="Show a button")
async def button(interaction: discord.Interaction):
    await interaction.response.send_message("Press the button:", view=Clicker())


bot.run(os.getenv("DISCORD_TOKEN"))

Run it on ServerSpark

  1. Put your token in a .env file: DISCORD_TOKEN=your-token-here. Never share it.
  2. Upload the files under Files in SparkPanel (or use SFTP).
  3. Under Settings, check the startup file: index.js (Node.js) or app.py (Python).
  4. Click Start. Packages are installed automatically; the console shows Logged in as … or any error.

Type /button in your Discord server. A new slash command can take a minute to show up.

Your data.db is a normal file in your bot's folder. Download it under Files now and then as an extra copy, especially before big changes.

Frequently asked questions

Is SQLite enough, or do I need MySQL? For most bots (one bot, up to thousands of servers) SQLite is fine and much simpler. You'd only need a separate database server when several programs write to the same data at once.

The button says "This interaction failed". The bot didn't reply within 3 seconds, or it was offline. Check the console in SparkPanel for an error.

New to bots? Start with Make a Discord bot with JavaScript or in Python, then read Run your Discord bot 24/7.