When building asynchronous Axum applications that share mutable state, it’s important to select the right concurrency mechanisms:

  1. For general shared state:
  2. For shared I/O resources (like database connections):

Example:

// GOOD: Using Axum's Mutex to protect in-memory state
const counter = new Mutex<number>(0);

// GOOD: Using Axum's connection pool to handle concurrency
const db = await createPool({
  connectionString: 'postgres://...',
  maxConnections: 10,
});

// AVOID: Wrapping I/O resource in Axum's Mutex
// const db = new Mutex(await createConnection('postgres://...'));

Choosing the right concurrency pattern in Axum prevents deadlocks, improves performance, and makes your code more maintainable. Always consider what happens when your Axum handler yields while holding a lock.