Skip to content

Revision · Project 3 — apilite

Project 3 built apilite, a real async REST API for a notes resource with full CRUD over HTTP and a SQLite database behind it. A web server is concurrency for a living, and this is where Rust’s concurrency story pays off. Here’s what to carry forward.

  • Async and lazy futuresasync/.await lets a handful of OS threads drive thousands of requests; the one surprise is that futures are lazy and do nothing until awaited.
  • axum routing and extractors — a router maps methods and paths to handlers, and typed extractors turn parts of the request (path, JSON body, state) directly into your function arguments.
  • JSON with serde — request and response types derive (de)serialization, so JSON in and out is generated from your structs rather than hand-parsed.
  • Shared state, cheaply cloned — a sqlx connection pool lives in State behind a cheap Arc clone, and Send/Sync bounds are the compiler guarding data shared across .await points and tasks.
  • Real SQL, safelysqlx runs async queries against SQLite with no ORM magic; you always bind parameters instead of building SQL with format!(), which closes off injection.
  • Errors as HTTP — one closed AppError enum implements IntoResponse, so ? turns a failure into the correct status code, From converts library errors in, and internal details never leak to the client.
  • Middleware and config — a tracing layer wraps every request with method, path, status, and latency, and configuration is read from the environment.
  • Testing and Docker — the oneshot pattern drives the router in-process against an in-memory SQLite so each test is hermetic, a library crate makes the app importable, and a multi-stage Dockerfile ships a small image.

For an API the recurring question sharpens: a server shares data across many simultaneous tasks, and “shared XOR mutable” now guards state across .await points and threads, surfacing as the Send/Sync bounds axum quietly requires. Each refusal is a data race deleted before it ships. With HTTP as a server behind you, Project 4 flips the arrow and makes you the client, calling the Claude API.