The Java template runs Java 21 and starts one jar. The default jar name is bot.jar.
Deploy in four steps
- Build a shaded jar on your own machine, so the dependencies are inside it. The Gradle file below does this with
./gradlew shadowJar. - Upload the jar in the file manager or over SFTP.
- Name it
bot.jar, or set Jar file (JAR_FILE) to its name. - Paste your token into Bot token (
BOT_TOKEN), then restart and wait forBOT_READY.
A minimal bot
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()
}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
# 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_READYThe 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
- Upload the whole Gradle project:
gradlew, thegradlefolder,build.gradle,settings.gradle, andsrc. - Keep the Shadow setup above so
shadowJarproduces the jar that the Jar file setting points at. - Set Build on start (
BUILD_ON_START) to1and restart.
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