Open-Source Wikis

/

Bitwarden Server

/

Bitwarden Server

/

Architecture

bitwarden/server

Architecture

Bitwarden Server is a polyglot-persistence multi-service .NET application. Every client talks first to the Identity service to obtain an OAuth access token, then to the Api service for vault operations, while a handful of supporting services (Events, EventsProcessor, Notifications, Admin, Billing, Icons, plus the commercial Sso and Scim projects) handle telemetry, real-time push, internal operations, payments, and enterprise integrations.

High-level service map

graph LR
    subgraph Clients
        Web["Web Vault"]
        BrowserExt["Browser Extension"]
        Mobile["Mobile / Desktop"]
        CLI["bw CLI"]
    end

    subgraph BitwardenServer
        Identity["Identity\n(OAuth/OIDC)"]
        Api["Api"]
        Events["Events\n(write API)"]
        EP["EventsProcessor\n(queue drain)"]
        Notifications["Notifications\n(SignalR hub)"]
        Admin["Admin\n(Razor Pages)"]
        Billing["Billing\n(Stripe/PayPal\nwebhooks)"]
        Icons["Icons\n(favicon proxy)"]
        Sso["Sso\n(SAML/OIDC IdP\nbridge)"]
        Scim["Scim\n(provisioning API)"]
    end

    subgraph Storage
        SqlDb[("SQL Server\n/MySQL/Postgres")]
        Blobs[("Azure Blob /\nLocal Files")]
        Cache[("Redis /\nDistributedCache")]
        Bus[("Service Bus /\nRabbitMQ /\nAzure Queue")]
    end

    Stripe["Stripe / PayPal /\nBraintree"] --> Billing
    Web -->|access token| Identity
    BrowserExt --> Identity
    Mobile --> Identity
    CLI --> Identity
    Web -->|JWT| Api
    BrowserExt --> Api
    Mobile --> Api
    CLI --> Api
    Mobile -->|WebSocket| Notifications
    Web --> Notifications
    Api -->|publishes| Events
    Events --> Bus
    Bus --> EP
    EP --> SqlDb
    Api --> SqlDb
    Api --> Blobs
    Api --> Cache
    Identity --> SqlDb
    Notifications --> Bus
    Sso --> Identity
    Scim --> SqlDb
    Admin --> SqlDb

Every box in BitwardenServer is a separate ASP.NET Core process with its own Startup.cs, Dockerfile, appsettings.*.json, and entry-point script.

Service responsibilities

Service Role Key entry point
Identity OAuth 2.0 / OIDC token endpoint built on Duende IdentityServer. Handles login, password authentication, two-factor auth, device-trust, refresh, SSO callbacks, and the SCIM token issuer. src/Identity/Startup.cs, src/Core/Auth/IdentityServer/
Api The main REST API for clients. Vault CRUD, organization management, sends, account settings, devices, billing self-service, secrets manager. src/Api/Startup.cs
Admin Razor-Pages admin UI for Bitwarden staff. Customer-support tools, billing operations, license generation, send/notification/log lookup. src/Admin/Startup.cs
Billing HTTP receiver for Stripe, PayPal IPN, BitPay, Braintree, and FreshDesk webhooks. Updates subscriptions and invoices in the database. src/Billing/Startup.cs
Events Tiny write API the clients hit to record user actions. Persists to a queue. src/Events/Startup.cs
EventsProcessor Background service that drains the event queue into the Event table (and Cosmos DB / Azure Table Storage in cloud). src/EventsProcessor/Program.cs
Notifications SignalR hub clients connect to for real-time vault sync, login requests, and notification-center messages. src/Notifications/NotificationsHub.cs, src/Notifications/HubHelpers.cs
Icons Public favicon-proxy that fetches and caches website icons used by client autofill. src/Icons/
Sso (commercial) SAML/OIDC bridge that lets enterprise users sign in to Bitwarden via their corporate IdP. Calls back into Identity. bitwarden_license/src/Sso/
Scim (commercial) SCIM 2.0 provisioning API for enterprise directory sync. bitwarden_license/src/Scim/

Each service registers shared Bitwarden services through services.AddBaseServices(globalSettings) and services.AddDefaultServices(globalSettings) in src/Core/Utilities/ServiceCollectionExtensions.cs, then layers in service-specific bindings (e.g. services.AddCustomIdentityServices in the Identity host, services.AddBillingOperations in the API).

Request lifecycle (typical authenticated API call)

sequenceDiagram
    participant C as Client
    participant I as Identity
    participant A as Api
    participant DB as SQL Server
    participant B as Service Bus
    participant E as EventsProcessor

    C->>I: POST /connect/token (password grant + 2FA)
    I->>DB: validate user, master-password hash
    I-->>C: access_token + refresh_token (JWT)
    C->>A: GET /sync (Bearer JWT)
    A->>DB: read User + Ciphers + Folders + Sends...
    A-->>C: SyncResponseModel
    C->>A: PUT /ciphers/{id} (modified item)
    A->>DB: UPDATE Cipher
    A->>B: enqueue CipherUpdated event
    B->>E: deliver event
    E->>DB: INSERT Event row
    A->>Notifications: push CipherUpdate to user devices

Data layer

The repository is unusual in supporting four databases for self-hosters and one (SQL Server) for the cloud. The shape is identical, but the two implementations live side-by-side:

  • SQL Server (canonical, Dapper)src/Sql/dbo/ is a SQL Server Database Project (.sqlproj) with every table, view, function, and stored procedure. Every repository under src/Infrastructure.Dapper/Repositories/ calls those stored procedures via Dapper. SQL change scripts ship in util/Migrator/DbScripts/ and are applied by MsSqlMigratorUtility.
  • MySQL / Postgres / SQLite (Entity Framework)src/Infrastructure.EntityFramework/ defines DatabaseContext, mappers, and EF IRepository implementations. Migrations live in util/MySqlMigrations/, util/PostgresMigrations/, and util/SqliteMigrations/. The provider is selected at startup by globalSettings.DatabaseProvider.

Every repository is registered against an interface (e.g. ICipherRepository); services.AddDatabaseRepositories(globalSettings) (src/SharedWeb/Utilities/ServiceCollectionExtensions.cs) picks the right concrete based on the configured provider. Application code never touches Dapper or EF directly — see systems/data-infrastructure.

Shared cross-service plumbing

Concern Lives in Notes
Configuration src/Core/Settings/GlobalSettings.cs Strongly-typed root-level settings bound from appsettings.*.json, env vars, and Azure Key Vault.
Auth/JWT src/Core/Auth/IdentityServer/, src/SharedWeb/Utilities/ServiceCollectionExtensions.cs (AddIdentityAuthenticationServices) All services use the same Bearer scheme pointing at the Identity host.
Push src/Core/Platform/Push/, src/Core/Platform/PushRegistration/ Multi-provider: Azure Notification Hub, SignalR, relay; selects via settings.
Event publishing src/Core/Services/Implementations/EventService.cs plus Service Bus / RabbitMQ / Azure Queue clients The EventService writes either directly or onto a queue depending on host.
Mail src/Core/Platform/Mail/HandlebarsMailService.cs plus src/Core/MailTemplates/ All transactional email rendered server-side from MJML/Handlebars templates.
Caching services.AddDistributedCache(globalSettings) (src/SharedWeb/Utilities/DistributedCacheServiceCollectionExtensions.cs) Redis in cloud, in-memory in self-host by default.
Health src/SharedWeb/Health/ /healthz and /healthz/extended endpoints on every cloud-hosted service.
Rate limiting src/Core/Utilities/CustomIpRateLimitMiddleware.cs plus IpRateLimitOptions/IpRateLimitPolicies from appsettings.json AspNetCoreRateLimit library, disabled in self-host.

Authentication flows

  • Master-password loginIdentity accepts the password grant, calls IUserService.CheckPasswordAsync, issues access + refresh tokens, optionally enforces 2FA via TwoFactorAuthenticationValidator.
  • Two-factor — TOTP, Email, Duo, YubiKey, WebAuthn, Remember tokens; providers live in src/Core/Auth/Identity/TokenProviders/.
  • WebAuthn passwordless / Login with deviceWebAuthnLoginGrantValidator + the Auth/UserFeatures/WebAuthnLogin/ commands.
  • SSO — corporate SAML/OIDC IdP → bitwarden_license/SsoIdentity's sso extension grant. Org-controlled per-user policies enforce SSO usage.
  • Trusted-device encryption (TDE) — admin-approval / device-key flow; see src/Core/Auth/UserFeatures/DeviceTrust/.
  • API keys — organisations and personal users can mint client-credentials API keys; validated through ApiClient extension grant.
  • SCIM bearer tokens — issued by the cloud control plane and validated in bitwarden_license/Scim.

Background work and integrations

  • Quartz.NET jobs — registered by JobsHostedService in each app (src/Api/Jobs/, src/Admin/Jobs/, src/Billing/Jobs/, src/Notifications/Jobs/, bitwarden_license/src/Sso/Jobs). Cleanup of expired devices, send tokens, sponsorships, and so on.
  • Hosted servicesApplicationCacheHostedService (Service Bus topic that invalidates IApplicationCacheService), AzureQueueHostedService (Notifications), HeartbeatHostedService (SignalR keep-alive), EventRepositoryHandler (EventsProcessor).
  • Event integrationssrc/Core/AdminConsole/Services/Implementations/EventIntegrations/ plus per-org Slack/Teams/HEC/webhook integrations.
  • Pushsrc/Core/Platform/Push/ abstracts Azure Notification Hub, SignalR notifications, and relay-mode push (the relay is what self-hosted instances use to forward push to Bitwarden's cloud Notification Hub).

Cloud vs. self-host

The same codebase ships in both modes. Self-host differences are conditional on globalSettings.SelfHosted:

  • IP rate limiting is disabled in self-host (Startup.Configure).
  • Health-check endpoints are not exposed in self-host.
  • Stripe / Braintree / PayPal / BitPay are skipped; subscriptions are handled by the licensed-organization flow.
  • Push uses the relay (Bitwarden's cloud notification hub) by default.
  • The Setup utility in util/Setup/ is the install-time bootstrapper that generates an installation ID/key and the on-disk global.override.env.

See deployment for the full picture.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Bitwarden Server wiki | Factory