Feature Flags & cfg
Use Cargo features and #[cfg(feature = ...)] to gate debug logs, dev-only instructions, and cluster-specific code in Anchor programs.
Search across all documentation pages
Use Cargo features and #[cfg(feature = ...)] to gate debug logs, dev-only instructions, and cluster-specific code in Anchor programs.
[features]
default = []
debug-log = []
devnet-only = []#[cfg(feature = "debug-log")]
msg!("debug");When to reach for this: You need different builds for dev vs mainnet or optional diagnostics.
Gate the instruction, not the #[program] module. Two cfg-selected modules with the same name are fragile and easy to get wrong; a single module with a cfg-gated handler compiles cleanly and keeps one IDL shape per build.
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod my_program {
use super::*;
pub fn settle(_ctx: Context<Settle>) -> Result<()> {
Ok(())
}
/// Compiled out entirely unless `--features devnet-only`.
#[cfg(feature = "devnet-only")]
pub fn airdrop_test_tokens(_ctx: Context<Airdrop>) -> Result<()> {
Ok(())
}
}
#[derive(Accounts)]
pub struct Settle<'info> {
pub authority: Signer<'info>,
}
#[cfg(feature = "devnet-only")]
#[derive(Accounts)]
pub struct Airdrop<'info> {
pub authority: Signer<'info>,
}What this demonstrates:
Accounts structs together, not the #[program] moduleSplitting #[program] modules by cfg changes IDL between builds. Prefer separate dev crates or instructions behind admin keys instead of shipping dev ix to mainnet.
Use constants in Anchor.toml / build scripts rather than multiple #[program] mods when possible.
| Alternative | Use When | Don't Use When |
|---|---|---|
| Separate dev program crate | Clear separation | Feature flags in one crate |
| Runtime admin gate | Same binary | Compile-time removal |
0.32.1 across advanced topics.
Large fixed layouts when Borsh CU too high.
Not easily; plan forward growth.
No; document separately.
Callee IDL JSON at compile time.
Yes with correct account metas.
Avoid different IDL per feature on mainnet.
LiteSVM, Surfpool, devnet simulation.
No; last resort.
See Related links for features.
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.
Reviewed by Chris St. John·Last updated Jul 19, 2026