Open-Source Wikis

/

MongoDB

/

How to contribute

/

Patterns and conventions

mongodb/mongo

Patterns and conventions

The MongoDB codebase has well-established conventions, many of them encoded in tooling. This page summarizes the ones every contributor encounters.

C++ style

The full style guide is docs/cpp_style.md — ~44 KB and unusually detailed by industry standards. Highlights:

  • C++20 is the baseline. Ranges, concepts, <format>, and the new <chrono> types are all in use.
  • clang-format with the rules in .clang-format is mandatory. bazel run format reformats the tree.
  • clang-tidy with custom checks in buildscripts/clang_tidy/ is run on Evergreen.
  • No raw new/delete in new code. Use std::make_unique, std::make_shared, or the in-tree std::unique_ptr aliases.
  • std::string over const char*, std::string_view over either when not owning.
  • Status and StatusWith<T> for recoverable errors; tassert/uassert/iassert for invariants.

Error handling

The full design is docs/exception_architecture.md. The contract:

  • Exceptions are typed with ErrorCodes. ErrorCodes are stable numeric IDs declared in src/mongo/base/error_codes.yml.
  • uassert(code, msg, expr) — user-facing assertion. Raises AssertionException if expr is false. Maps to a server error response.
  • iassert(...) — internal assertion. Same as uassert but for invariants the user shouldn't normally see.
  • tassert(...) — like iassert, but additionally opens a JIRA ticket via the FTDC dump on production hits.
  • invariant(...) — hard fatal. Aborts the process. Use only for unrecoverable program-state corruption.
  • Status — non-throwing error code + message. Returned by APIs that can fail without exceptional cost.
  • StatusWith<T>Status plus a value when ok. The result type for "compute a value or fail" APIs.

The MONGO_UNREACHABLE macro marks unreachable code; MONGO_UNREACHABLE_TASSERT(N) opens a ticket if executed.

OperationContext and Client

Almost every API in src/mongo/ takes an OperationContext* (often abbreviated opCtx). It owns:

  • The current storage RecoveryUnit (the transaction).
  • Cancellation state (isKillPending(), checkForInterrupt(), deadlines).
  • Decorations — typed slots subsystems use to attach state.
  • A back-pointer to the Client, which is the per-thread state.
Status doSomething(OperationContext* opCtx) {
    opCtx->checkForInterrupt();
    AutoGetCollection coll(opCtx, nss, MODE_IS);
    // ...
}

The Client has a back-pointer to the process-wide ServiceContext. Any code that needs a "thread-local" really wants a decoration on one of those three.

IDL (interface definition language)

Commands, BSON types, server parameters, and config documents are declared in YAML files with the .idl extension. The IDL compiler (buildscripts/idl/) generates the C++ code that parses, serializes, and validates them. See IDL and docs/idl.md.

commands:
  myCommand:
    description: 'An example command'
    namespace: concatenate_with_db
    api_version: '1'
    fields:
      n:
        type: int
        description: 'How many iterations'
        default: 1

Most commands are declared this way. The generated code provides a typed MyCommandRequest struct that's parsed from BSON in one line.

Smart pointers

  • std::unique_ptr<T> for unique ownership.
  • std::shared_ptr<T> only when the lifetime really must be shared. Prefer transferring ownership over sharing.
  • Internal types use names like Collection::Ptr, ScopedCollectionAcquisition, and AutoGetCollection to express scoped acquisition with locking semantics.

Locking

The lock manager (src/mongo/db/concurrency/) is one of the older, more intricate subsystems. The high-level rule for new code:

  • Use the shard role API (shard_role.h::acquireCollection) rather than the legacy AutoGetCollection/Lock::DBLock directly when possible.
  • Acquire locks in the documented hierarchy: global → database → collection.
  • Don't call Lock::* from inside a future continuation unless that continuation is explicitly running on a baton or thread that owns an OperationContext.

Decorations

A decoration is a typed slot attached to a Service, Client, OperationContext, or Collection. They are the project's answer to "I need per-X state without modifying X." Implemented in src/mongo/util/decorable.h.

namespace {
auto getMyState = OperationContext::declareDecoration<MyState>();
}

void useState(OperationContext* opCtx) {
    auto& s = getMyState(opCtx);
    // ...
}

Decorations are zero-overhead at access time and typed.

Futures and promises

Asynchronous work uses the Future<T>/Promise<T>/SemiFuture<T> types in src/mongo/util/future.h. The design is in docs/futures_and_promises.md.

Key rules:

  • Continuations attached with .then() run on the executor that completed the future, unless re-bound with .thenRunOn(executor).
  • For "wait for async work to finish on this thread", use a Baton — see docs/baton.md.
  • Avoid blocking calls (get()) inside continuations. Use .then() chains and let the framework drive completion.

Fail points

Inject MONGO_FAIL_POINT_DEFINE(name); at file scope and check it inline:

if (auto fp = MONGO_FAIL_POINT_DEFINE(myFailPoint); fp.shouldFail()) {
    // injection logic
}

Tests enable the fail point with configureFailPoint. See Fail points.

Server parameters

Tunable knobs are declared in IDL files under *.idl with server_parameters: blocks and read by the generated <name>::get(ServiceContext*) accessor. The full picture is in docs/server_parameters.md.

Logging

Log lines use the LOGV2_* macros and a stable numeric ID:

LOGV2(123456, "Did the thing", "field"_attr = value);

Every log call needs a unique ID. The IDs are reserved per-team via the etc/log_id_ranges.yml table. See logv2 and docs/logging.md.

Modules

Every C++ file is assigned to a module declared in modules_poc/modules.yaml, and APIs are marked with visibility attributes from src/mongo/util/modules.h (PUBLIC, PRIVATE, FILE_PRIVATE, NEEDS_REPLACEMENT, etc.). The modules_poc/ tooling enforces that no module accesses another's private API. See Modularity and docs/modularity.md.

What this page does not cover

  • The aggregation pipeline's stage authoring conventions — see src/mongo/db/pipeline/.
  • Replication-specific patterns (oplog entries, primary-only services) — see Replication.
  • Sharding's distributed-coordinator patterns — see Sharding.

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

Patterns and conventions – MongoDB wiki | Factory