Serenity 0.12: eleven default features, one of them already deprecated
A Rust library for the Discord API.
At a glance
- What is it?
- Serenity is a Rust library for the Discord API under an ISC license, shipping as crate version 0.12.5 with Rust 1.74 as its floor. Its default feature set switches on a framework the project itself deprecated at 0.12.1, and its examples are workspace members rather than a separate download.
- Who is it for?
- Serenity suits a Rust developer who wants shard handling, event dispatch and a cache in the box and does not mind pulling eleven default features to get them. Before you commit, check whether your host can spare the memory the cache wants, confirm a TLS backend decision before you set default-features = false, and read the 0.12.1 note on standard_framework so you do not build a command layer the project wants you to replace with poise.
- Can I use it commercially?
- Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- serenity-rs/serenity5,657 ★ · +44
| Repository | 2026-09-23 | 2026-11-14 |
|---|---|---|
| serenity-rs/serenity | 5.6k | 5.7k |
44 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Two lines in Cargo.toml, and the tokio floor is not the one serenity builds on
Installation is a dependency stanza and a version string. The crate is 0.12, and tokio arrives with the macros and rt-multi-thread features:
[dependencies]
serenity = "0.12"
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }That second line deserves a second look. The library's own manifest pins tokio 1.34.0 with the features fs, macros, rt, sync, time and io-util, so 1.21.2 in the snippet is a floor rather than the version serenity is compiled against. Cargo merges features across a dependency graph, which is also why rt-multi-thread has to appear in your manifest at all: serenity never asks for it, yet the ping-pong example marks its entry point with #[tokio::main] and spreads work over threads. First run is three moves: log in through Client::builder, implement EventHandler for a plain struct, and match on msg.content inside async fn message, where msg.channel_id.say(&ctx.http, "Pong!") writes the reply. The token is read from the environment as DISCORD_TOKEN, and validate_token exists to check one before you attempt a login.
The default set still switches on the framework it tells you to stop using
Adding serenity with no feature configuration turns on eleven of them: builder, cache, chrono, client, framework, gateway, http, model, standard_framework, utils and rustls_backend. One of the eleven is marked deprecated as of v0.12.1. That one is standard_framework, the stock implementation behind the framework feature, and the note points at poise as the replacement. So a default build carries code the project has retired, and removing it means opting out of everything else and re-picking the list by hand. Inside the list, gateway is the Shard speaking to the gateway over a WebSocket client, http wraps the REST API low enough that optional parameters can be handed over through a JsonMap, model sits on http as helper methods on the data types, and collector lets you await events with criteria attached. Voice is not in the default set.
The cache fills from events and is searched before every HTTP call
Caching is a feature choice, not a given. When cache is enabled it holds information about guilds, channels, users and other data, and it fills as events arrive rather than by polling. Calling a method on a Context searches that cache first so the library can skip REST requests it does not need, and that is the main reason to leave the feature on. The advice for a small machine is blunt: if you are low on RAM, do not enable this. Turning it off is the expensive direction, because cache ships inside the eleven defaults rather than standing alone, so switching it off means starting from default-features = false and rebuilding the list yourself. For callers that just fetched a value over HTTP, temp_cache is the narrower door, keeping temporary caching inside those retrieval functions.
MSRV 1.74 is held on current, and dependencies can break the build anyway
The toolchain floor is called the MSRV and it is Rust 1.74, declared once in the workspace package as rust-version = "1.74" beside edition = "2021". The policy runs on two branches. On current the floor stays put between minor releases, and a new major release is the only event that moves it. On next the floor tracks the newest Rust release so stabilized language features arrive sooner. The distance between those branches is where the documented pain sits: dependencies sometimes violate SemVer and raise their own MSRV in a way that breaks you, and the stated remedy is to pin their versions until the build works again on the older compiler. A library that keeps its own floor stable cannot keep its dependencies' floors stable for you, so a Cargo.lock earns its place in this stack.
rustls_backend by default, and three features that need a build flag or a CPU
TLS is settled in the manifest. The default set ends in rustls_backend, so an untouched dependency line picks rustls without asking. Two alternatives require default-features = false: default_native_tls swaps in native_tls_backend, and default_no_backend drops the backend entirely so you can supply your own. Three more features carry preconditions that the bullet list does not shout about. tokio_task_builder enables tokio's tracing feature and uses tokio::task::Builder to spawn named tasks, but only when RUSTFLAGS="--cfg tokio_unstable" is set at build time, which means a build script or an environment file rather than a manifest line. simd_json turns on accelerated JSON parsing and rendering, and only where the target CPU supports it. chrono represents timestamps with the chrono crate; disable it and the time crate takes that job, and time is already a required dependency at 0.3.36 with formatting, parsing and serde-well-known enabled.
Cargo.toml pins 0.12.5 while the branch moved on ten months later
The manifest and the release list have drifted apart in time rather than in number. Cargo.toml declares version = "0.12.5", which matches the newest tag, v0.12.5, published on 2025-12-20. The two tags before it are v0.12.4 on 2024-11-15 and v0.12.3 on 2024-11-12, three days apart, and then v0.12.5 arrives more than a year after them. The last push on the default branch is dated 2026-10-31, so work keeps landing on that branch without a matching crates.io release. Nothing in the manifest marks the 0.12 line as a moving channel, since 0.12.5 is an ordinary release number rather than a prerelease tag. A Cargo.toml pinned to 0.12 therefore keeps resolving to the same published version while the clone next to it holds newer commits, which is the arrangement to keep in mind when a bug reproduces on one and not the other.
examples/* are workspace members, so --workspace builds nineteen sample bots
The examples are part of the build rather than a separate download. The workspace declares members = ["examples/*"], so each numbered sample is a crate in its own right: e01_basic_ping_bot through e19_interactions_endpoint, plus a testing directory and their own examples/README.md and examples/Makefile.toml. The directory names double as a feature index: e02_transparent_guild_sharding, e08_shard_manager, e10_collectors, e11_gateway_intents, e14_slash_commands, e16_sqlite_database, e17_message_components, e18_webhook. Elsewhere the repository root carries benches/, tests/, build.rs, clippy.toml, rustfmt.toml, command_attr/ and voice-model/, alongside a .cargo/ directory and a .git-blame-ignore-revs file that keeps formatting commits out of blame views. The practical consequence is that a workspace-wide cargo build --workspace or cargo test --workspace pulls in every sample bot, so a slow compile in one example is a cost you pay for the whole set.
Voice, slash commands and authoritative docs all live somewhere else
Three jobs are handed off rather than done. Voice connections are not built in: the voice feature only registers a voice plugin with the client and lets that plugin handle the actual connection, and lavalink-rs and Songbird are named as the recommended plugins. Command handling is split too. The framework feature is described as simple command parsing with prefix setting and before or after execution, which is why poise exists as a framework built on top of serenity for slash commands or text commands. Documentation authority is the third gap, and the project states it openly: Discord hosts the official documentation, and if a detail matters you should refer to that instead of this README. The unstable_discord_api feature makes the same point from the other side, naming endpoints that have no official documentation and may change. Sharding sits in between: the README says the Shard is handled transparently, while the example names point at both a transparent path and a manual shard manager.
Editorial conclusion
Serenity suits a Rust developer who wants shard handling, event dispatch and a cache in the box and does not mind pulling eleven default features to get them. Before you commit, check whether your host can spare the memory the cache wants, confirm a TLS backend decision before you set default-features = false, and read the 0.12.1 note on standard_framework so you do not build a command layer the project wants you to replace with poise.
Frequently asked questions
How do you use Serenity to get a Rust Discord bot online?
Add serenity = "0.12" plus tokio with the macros and rt-multi-thread features, log in with Client::builder, implement EventHandler for a struct, and match on msg.content inside async fn message, where msg.channel_id.say(&ctx.http, "Pong!") sends the reply. The token is read from the environment as DISCORD_TOKEN.
What is the minimum Rust version Serenity 0.12 needs?
Rust 1.74, declared as rust-version in the workspace package. The floor stays fixed between minor releases on the current branch, while the next branch tracks the newest Rust release, and a new major release is what updates the floor on current.
Should the cache feature stay off on a small server?
The cache stores guilds, channels, users and other data so the library can skip REST requests, and the README says not to enable it if you are low on RAM. Turning it off means setting default-features = false and listing the features you want yourself.
Which crate handles voice when using Serenity?
Not serenity itself. The voice feature only registers a voice plugin with the client, and lavalink-rs and Songbird are the recommended plugins for the actual voice connections.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/serenity-rs-serenity)Star history chart for your README
[](https://hysenlabs.com/projects/serenity-rs-serenity)Was this useful?