A Bot That Stays Up
Sharding, session resume, a clean shutdown and a restarting supervisor are all in the SDK

An Automatic Shard Count
A shard is one gateway connection, carrying the events of part of the bot's communities. With sharding: "auto", the SDK counts the communities at the first connect and opens one shard for every 2,000
When the bot outgrows that plan while it runs, Fluxer closes a shard with code 4011, and the SDK moves every shard to a larger plan in the same process. The bot keeps running. Events sent during the move are missed, and the move is logged once at Warn
import { runBot } from "@neontechspace/fluxerly"await runBot({ token: process.env.FLUXER_BOT_TOKEN, sharding: "auto", events: { messageCreate: ({ message, reply }) => { if (message.content !== "!ping") return undefined return reply("Pong!") }, },})Restarts That Resume
A restarted bot normally starts new sessions and misses what happened while it was down. Fluxer keeps a disconnected session for 60 seconds, and fileSessionStore saves each shard's session at a clean shutdown and offers it at the next start. Its folder, sessions here, holds session IDs that let the token resume a session, so keep it out of version control and readable only by the bot's account
A quick restart, such as a deploy, then resumes and receives the missed events within Fluxer's replay limits. Each snapshot is written to a temporary file and renamed into place, so a crash never leaves a half-written one, and a store problem never stops the bot
import { fileSessionStore, runBot } from "@neontechspace/fluxerly"await runBot({ token: process.env.FLUXER_BOT_TOKEN, sharding: { totalShards: "auto", sessions: fileSessionStore("sessions") }, events: { messageCreate: ({ message, reply }) => { if (message.content !== "!ping") return undefined return reply("Pong!") }, },})A Stop That Finishes the Work
Ctrl+C, or the SIGTERM a process manager sends, asks the bot to stop. It stops taking new events, lets running handlers and their requests finish for up to five seconds, a time drainMs changes, then cancels what is left and closes the connection
runBot never exits the process. Once it resolves, the application closes what it opened, and Node.js ends on its own

import { runBot } from "@neontechspace/fluxerly"// Something the application opened itself, such as a database connection or a timerconst heartbeat = setInterval(() => console.info("Still running"), 60_000) // Ctrl+C, or SIGTERM from a process manager, asks the bot to stop, and running// handlers then get up to 10 seconds to finishawait runBot({ token: process.env.FLUXER_BOT_TOKEN, drainMs: 10_000, events: { messageCreate: ({ message, reply }) => { if (message.content !== "!ping") return return reply("Pong!") }, },})// runBot never exits the process. Close what the application opened, then Node.js ends clearInterval(heartbeat) 
Crashed Processes Come Back
When one process is not enough, the SDK's supervisor starts several Node.js child processes, gives each its shards and stops them all on shutdown
A child that exits unexpectedly is replaced, up to three times in a row with a growing delay. A child that runs for a minute after becoming ready gets its full budget back, so only a crash loop uses it up
import { describeError, supervisor } from "@neontechspace/fluxerly"const workers = supervisor.create({ entry: new URL("./shard-worker.js", import.meta.url), token: process.env.FLUXER_BOT_TOKEN, totalShards: "auto", processes: 2,})const stop = () => { workers.shutdown().then(undefined, (defect: unknown) => { console.error(describeError(defect)) process.exitCode = 1 })}process.once("SIGINT", stop) process.once("SIGTERM", stop) const started = await workers.start() const closed = started.isOk() ? await workers.waitForClose() : started process.removeListener("SIGINT", stop) process.removeListener("SIGTERM", stop) if (closed.isErr()) { console.error(describeError(closed.error)) process.exitCode = 1 }Gateway Health and Worker Health, Apart
A connected bot can still have a stopped subscription, the registration that delivers one event to its handler. A report on the connection alone would call that bot healthy
The supervision guide reports both side by side: The gateway's state, and the critical worker's state with its failure count. Health reports carry states and counts, never event bodies or raw exceptions
import type { ClientDiagnostics, ConnectionState } from "@neontechspace/fluxerly";export interface BotHealth { readonly gateway: ConnectionState; readonly criticalWorker: "starting" | "running" | "failed" | "stopped"; readonly handlerFailures: number;}export type SupervisedOutcome = | { readonly kind: "stopped" } | { readonly kind: "connection-failed"; readonly failure: string } | { readonly kind: "critical-worker-failed"; readonly failure: string };// The health callback receives both reports. Neither one stands in for the otherexport type ReportHealth = (health: BotHealth, diagnostics: ClientDiagnostics) => void; Deploy with the Token in the Environment
A deployed bot is an ordinary Node.js process. Here systemd reads the token from a file that only root can read, so the bot's own account never needs access to it, and the token never sits in the code
A stop sends SIGTERM and waits 30 seconds before forcing it, which leaves the drain and cleanup room to finish. systemd restarts the bot after a crash or a failing exit code, but not after a clean stop
[Unit]Description=Fluxer botWants=network-online.target After=network-online.target [Service]Type=simpleUser=fluxer-botWorkingDirectory=/srv/fluxer-bot EnvironmentFile=/etc/fluxer-bot.env ExecStart=/usr/bin/node bot.js Restart=on-failureRestartSec=5TimeoutStopSec=30[Install]WantedBy=multi-user.target 












