Deploy JDA

DeployUpdated JDA hosting

The Java template runs Java 21 and starts one jar. The default jar name is bot.jar.

Deploy in four steps

  1. Build a shaded jar on your own machine, so the dependencies are inside it. The Gradle file below does this with ./gradlew shadowJar.
  2. Upload the jar in the file manager or over SFTP.
  3. Name it bot.jar, or set Jar file (JAR_FILE) to its name.
  4. Paste your token into Bot token (BOT_TOKEN), then restart and wait for BOT_READY.

A minimal bot

build.gradle
plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '8.1.1'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'net.dv8tion:JDA:5.0.0'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

tasks.named('shadowJar') {
    archiveFileName = 'bot.jar'
    destinationDirectory = file('.')
    manifest {
        attributes 'Main-Class': 'Main'
    }
    mergeServiceFiles()
}
src/main/java/Main.java
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.session.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.build.Commands;

public class Main extends ListenerAdapter {
  public static void main(String[] args) {
    JDABuilder.createLight(System.getenv("BOT_TOKEN"))
        .addEventListeners(new Main())
        .build();
  }

  @Override
  public void onReady(ReadyEvent event) {
    event.getJDA().updateCommands()
        .addCommands(Commands.slash("ping", "Replies with pong"))
        .queue();
    System.out.println("BOT_READY");
  }

  @Override
  public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
    if (event.getName().equals("ping")) {
      event.reply("pong").queue();
    }
  }
}

The build writes bot.jar next to build.gradle, so the default Jar file works without changes. A plain jar without its dependencies fails with a class-not-found error.

What runs on start

What runs on start
# only when Build on start is 1 and gradlew exists
$ ./gradlew --no-daemon shadowJar
# if the jar is missing, the start stops here
$ java -Xms64M -Xmx(85% of plan memory) -jar bot.jar
BOT_READY

The heap is capped at 85% of the server memory, which leaves room for the JVM's own memory: threads, class data, and native buffers. If the bot still gets killed for memory, shrink JDA's caches, for example the member cache and chunking, or move to a bigger plan.

Build on start instead

  1. Upload the whole Gradle project: gradlew, the gradle folder, build.gradle, settings.gradle, and src.
  2. Keep the Shadow setup above so shadowJar produces the jar that the Jar file setting points at.
  3. Set Build on start (BUILD_ON_START) to 1 and restart.
Note

Building on start makes every start slower and uses the server's memory and CPU. On the free tier's 256 MB, build on your own machine and upload the jar.

Deploy from GitHub

On Free (public repositories) and paid plans, set Git repository (GIT_REPO), Git branch (GIT_BRANCH), and Auto update (AUTO_UPDATE) to 1, then restart. The first start clones the repository without deleting anything: files with the same names as files in the repository, such as an old bot.jar, move to a pre-git-backup- folder. With Build on start also at 1, every start fetches the branch and rebuilds the jar from the new source. Reinstall keeps existing files and defers the repository fetch to the next start with Auto update on. Backups and the reinstall steps are covered in deploy discord.js. Free public deploys must fit the free disk limit; private repositories need a paid plan. Uploading is covered in SFTP and the file manager.

Still stuck? Contact support