Learn / Rust Practical Systems
Ownership in Services
Use ownership and shared state deliberately so handlers stay simple and safe.
Course: Rust Practical Systems. Level: Intermediate. Topic: Systems reliability.
Stage: basic - Basic service state - Ownership in Axum service state. Use shared state, typed handlers, and response DTOs without fighting ownership.
Outcomes
- Choose Arc for shared immutable state.
- Keep handler signatures readable.
- Serialize response types cleanly.
Concepts
- ownership
- Arc
- state extractor
- serde
Concept flow
Show how ownership in axum service state moves from trigger to implementation outcome in Rust Systems.
- Router
- State
- Handler
- Response DTO
- Client
Session flow
- Model ownership (concept, 9 min) — Name the decisions behind ownership before writing code.
- Choose Arc for shared immutable state.
- Explain where ownership belongs in job orchestration service.
- Build the vertical slice (walkthrough, 17 min) — Implement the smallest useful slice in src/http.rs.
- Keep handler signatures readable.
- Connect Arc to a working example.
- Verify and harden (exercise, 11 min) — Write a handler test.
- Serialize response types cleanly.
- Record one risk or follow-up before moving on.
Code example
Rust in src/http.rs.
use axum::{extract::State, routing::get, Json, Router};
use serde::Serialize;
use std::sync::Arc;
#[derive(Clone)]
struct AppState {
version: Arc<str>,
}
#[derive(Serialize)]
struct Health {
ok: bool,
version: String,
}
async fn health(State(state): State<AppState>) -> Json<Health> {
Json(Health {
ok: true,
version: state.version.to_string(),
})
}
fn app(state: AppState) -> Router {
Router::new().route("/health", get(health)).with_state(state)
}
Walkthrough examples
- Ownership in Services in a job orchestration service — A team is extending an Axum service with a companion CLI and needs this lesson's pattern to be clear enough for review, testing, and future maintenance.
- File: src/http.rs
- File: tests/ownership-in-services.spec
- File: docs/rust-systems/ownership-in-services.md
- Start from the provided Rust snippet and make the intent visible in names and boundaries.
- Apply the checklist item "Define state type" before adding extra behavior.
- Write down how the implementation changes when Arc fails or becomes slow.
Practice
- Add one shared config value to state.
- Return a typed JSON response.
- Write a handler test.
Checklist
- Define state type
- Attach router state
- Serialize DTO
- Test handler
Quiz prompts
- Why wrap shared read-mostly state in Arc? — Arc gives multiple handlers shared ownership of immutable or internally synchronized state.
- A teammate wants to hide ownership inside a convenient helper. What should you check first? — Place ownership at the boundary that keeps job orchestration service behavior explicit, testable, and reviewable.
- Which artifact best proves this Rust Systems lesson is ready for review? — Production-ready learning needs evidence: a test, trace, command, screenshot, or log that catches the risk again.
- Basic service state: a teammate says the happy path works, but "Shared Arc state" is still implicit. What should you ask for before merging? — Shared Arc state belongs in the basic stage only when the decision is visible, testable, and tied to a realistic failure mode.
- A reviewer has five minutes to evaluate this basic Rust Systems slice. Which evidence is strongest? — Create the basic Axum state slice: shared typed state, clean handler signature, stable DTO, and a handler test.
Flashcards
- Basic service state: what decision does "Shared Arc state" force you to make? Share read-mostly application state across async handlers cheaply and safely. Evidence prompt: Add one shared config value to Axum state and explain why cloning is cheap.
- Basic service state: what decision does "Handler signature" force you to make? Keep extractor and return types readable so ownership rules are obvious to reviewers. Evidence prompt: Simplify one handler signature and move transformation code into a helper.
- Basic service state: what decision does "Serde boundary" force you to make? Separate internal types from API DTOs so serialization remains a stable contract. Evidence prompt: Create one response DTO and test its serialized shape.
- In Rust Systems, what should you remember about ownership? ownership matters here because it supports "Choose Arc for shared immutable state.".
- In Rust Systems, what should you remember about Arc? Arc matters here because it supports "Keep handler signatures readable.".
- In Rust Systems, what should you remember about state extractor? state extractor matters here because it supports "Serialize response types cleanly.".
- In Rust Systems, what should you remember about serde? serde matters here because it supports "Choose Arc for shared immutable state.".
Labs
- Ship a ownership in services slice — Extend an Axum service with a companion CLI with a small but reviewable feature that proves the lesson's architecture in code.
- Create the basic Axum state slice: shared typed state, clean handler signature, stable DTO, and a handler test.
- Add one shared config value to Axum state and explain why cloning is cheap.
- Simplify one handler signature and move transformation code into a helper.
- Create one response DTO and test its serialized shape.
- Add one shared config value to state.
- Return a typed JSON response.
- The lab demonstrates the basic service state outcome without skipping earlier contract evidence.
- Each subtopic has a concrete artifact: Shared Arc state, Handler signature, Serde boundary.
- The review notes explain how this level changes ownership, verification, or operational risk.
Challenge
- Review-ready ownership in services (Stretch) — Create the basic Axum state slice: shared typed state, clean handler signature, stable DTO, and a handler test.
- All checklist items are either implemented or documented with a reason.
- The change can be understood from src/http.rs plus one short note.
- The concept diagram names ownership, failure handling, and verification points.
- A teammate could run the verification steps without asking for hidden context.
Canonical lesson URL