Skip to content

Storage Adapters

authx-rs uses a ports and adapters (hexagonal) architecture for storage. The core defines what operations exist via traits; adapters define how they’re executed.

TraitResponsibility
UserRepositoryCRUD users, find by email/username/id, list paginated
SessionRepositoryCreate/invalidate sessions, find by token hash or user
CredentialRepositoryStore/retrieve password hashes, TOTP secrets, passkeys
OrgRepositoryOrganizations, roles, memberships
ApiKeyRepositoryAPI key CRUD, hash lookup, touch last_used_at
OAuthAccountRepositoryUpsert OAuth accounts, find by provider
InviteRepositoryCreate/accept/expire org invitations
AuditLogRepositoryAppend/query audit log entries
pub trait StorageAdapter:
UserRepository + SessionRepository + CredentialRepository +
OrgRepository + ApiKeyRepository + OAuthAccountRepository +
InviteRepository + AuditLogRepository + Send + Sync + 'static
{}
impl<T: UserRepository + SessionRepository + …> StorageAdapter for T {}

Implement all traits and your type is automatically a StorageAdapter — no extra boilerplate.

AdapterUse caseFeature flag
MemoryStoreTests, local dev(always available)
PostgresStoreProductionsqlx-postgres

When a type implements multiple traits that share a method name (e.g. both UserRepository and SessionRepository have create), you must use Fully Qualified Syntax:

// Correct
UserRepository::create(&self.storage, create_user_data).await?;
SessionRepository::create(&self.storage, create_session_data).await?;
// Won't compile — ambiguous
self.storage.create(data).await?;