Skip to content
ExponaBLOG
RUST PROGRAMMING · DAY 020 / 100

Cargo essentials: what every Rust developer should know

Commands you use every day.

Expona Admin6 min read

Introduction

By day 20 of your Rust journey, you've written functions, handled errors, and maybe even deployed something small. But your real productivity multiplier isn't advanced language features—it's mastering your build toolchain. Cargo essentials: what every Rust developer should know are the everyday commands that separate developers who fight their tools from those who work seamlessly within them.

We'll walk through the commands you'll use in production every single day, from building and testing to maintaining code quality and managing dependencies. These aren't flashy features. They're the foundation that lets you ship faster.

cargo build, run and test: your development loop

These three commands form the core of daily development. Let's start with what each does and when you actually use them.

cargo build compiles your project into an executable or library. By default, it targets debug mode—faster to compile, slower to run, full debug info. For a real-world scenario: you're building an HTTP service and want to iterate quickly. Debug builds give you that speed.

rust
cargo build

This places your binary in target/debug/. When you're ready to ship or benchmark, use:

rust
cargo build --release

Release builds take longer to compile but run significantly faster—typically 10-100x depending on workload. We learned this the hard way with a data pipeline that seemed slow until someone remembered we were still running debug builds in staging.

cargo run builds and executes your binary immediately. During development, this is your daily driver. No separate compile and execute steps.

rust
cargo run -- --config production.toml

The -- separator passes arguments to your program, not to cargo. Forget this once and you'll remember it forever.

cargo test compiles tests in test mode and runs them. By default it runs all tests in parallel.

rust
cargo test

You can filter tests by name:

rust
cargo test database_

This runs only tests with "database_" in their name. In a microservice with hundreds of tests, this saves mental cycles. You can also run a single test thread for ordering-dependent tests (unusual but happens):

rust
cargo test -- --test-threads=1

One pattern we use: run cargo test before every commit locally. It's cheap enough that skipping it eventually costs more in CI cycles.

cargo add for dependencies: the modern way

Manually editing Cargo.toml works, but cargo add is faster and smarter. It fetches the latest version, handles version constraints, and updates your lock file automatically.

rust
cargo add tokio

This adds tokio with its latest version. Behind the scenes, cargo queries crates.io and figures out compatible versions. Your Cargo.toml gets updated, usually with a caret constraint like tokio = "^1.40".

Specify features if needed:

rust
cargo add tokio --features full

Or a specific version:

rust
cargo add serde --version "1.0.200"

For development dependencies only:

rust
cargo add --dev criterion

This adds criterion (a benchmarking framework) to [dev-dependencies], so it won't bloat production builds.

Remove dependencies just as cleanly:

rust
cargo remove tokio

We've seen teams still manually editing TOML and checking what version is current by browsing crates.io in a browser tab. Cargo add eliminates that friction. It's one of the reasons newer Rust adoption is smoother than it was five years ago.

cargo fmt and cargo clippy: non-negotiable code quality

These two commands aren't optional if you're working in a team. They're your contract with your codebase.

cargo fmt automatically formats your code to Rust's standard style. Run it:

rust
cargo fmt

It modifies files in place. No bikeshedding about where braces go or whether to use two or four spaces. Consistency is enforced. In projects with 20+ developers, this alone eliminates countless review comments.

Check if your code is formatted without modifying it:

rust
cargo fmt -- --check

We run this in CI—if formatting isn't correct, the build fails. Forces everyone to run cargo fmt locally before pushing.

cargo clippy is a linter that catches common mistakes and suggests idiomatic Rust patterns.

rust
cargo clippy

Example output from real code:

rust
warning: you are using an explicit closure to convert something into `Result`
  |
  | .map(|v| Ok(v))
  |
  = note: Consider using `map_ok` instead

Clippy isn't always right—sometimes you have intentional code that triggers warnings—but it catches the kinds of mistakes that cost hours in production. We treat clippy warnings as seriously as errors. Run it with:

rust
cargo clippy -- -D warnings

The -D warnings flag denies warnings, treating them as errors. This is harsh but effective for maintaining code quality.

In your CI pipeline, both should be mandatory:

rust
cargo fmt -- --check
cargo clippy -- -D warnings
cargo test
cargo build --release

This four-step pipeline takes minutes and catches 95% of preventable issues before they hit main.

Cargo.lock: managing reproducibility for applications

This one trips up developers who come from other ecosystems. Cargo.lock is a file that locks exact dependency versions. Whether you commit it depends on what you're building.

For applications (binaries): Always commit Cargo.lock. This ensures everyone on your team, and your deployment environment, uses identical dependency versions. Reproducibility matters. We had a situation where a transitive dependency released a minor version that broke our observability integration—but our staging environment had already pulled it while production hadn't. The lock file prevents this.

For libraries: Don't commit Cargo.lock. Users of your library generate their own lock file with their own dependency versions. Committing yours just adds noise in version control.

Check your Cargo.toml. If you have [[bin]] sections, you're writing an application. Commit the lock file.

When dependencies need updating, you have options. Update everything:

rust
cargo update

Or target specific packages:

rust
cargo update -p tokio

This respects version constraints in Cargo.toml—so if you specified tokio = "^1.30", it updates to the latest 1.x, not 2.0.

Before merging any update to main, run your full test suite. Dependency updates should be treated like any other code change.

Common mistakes

Forgetting -- in cargo run: cargo run --config dev tries to run with config as a cargo flag, not your program's argument. Use cargo run -- --config dev. Easy to miss, annoying to debug.

Running tests in release mode without realizing it: If you need faster tests, cargo test --release exists, but remember that release mode optimizations can hide bugs that debug mode would catch. Use sparingly.

Committing Cargo.lock for libraries: It bloats your repository and forces unnecessary updates on your users. Check whether you're building a library or application.

Ignoring clippy warnings: They're not decoration. They often point to subtle logic errors or performance issues. Even the "harmless" ones are usually easier to fix now than debug later.

Not using cargo add: We've seen developers manually edit Cargo.toml and get syntax wrong or forget to update the lock file. Cargo add handles all this. It's faster and more reliable.

Key takeaways

  • cargo build, cargo run, and cargo test form your development loop. Debug mode for speed, release mode for performance.
  • cargo add and cargo remove are the modern way to manage dependencies—faster and more reliable than manual TOML editing.
  • cargo fmt enforces consistent style across teams. Make it mandatory in CI, not optional.
  • cargo clippy catches idiomatic and performance issues before code review. Treat warnings seriously.
  • Commit Cargo.lock for applications, not libraries. It ensures reproducible builds in production.
  • Wire all of these into your CI pipeline. Consistency and quality compound over time.
---
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles