Does Mongoose provide built-in retry middleware that guarantees at-most-once semantics for write operations?
0 reputation · 23 Jul 2020, 13:41 UTC
0 reputation · 23 Jul 2020, 13:41 UTC
When using Mongoose for write operations, developers often need to handle transient failures such as network glitches or primary elections without causing duplicate effects.
The goal is to configure a retry mechanism that automatically retries failed writes while ensuring each logical write is applied at most once, even if the underlying driver retries after the write succeeded but before the response is received.
Currently Mongoose does not ship a built-in retry middleware; users must rely on the MongoDB driver's retryable writes or implement their own logic, which raises uncertainty about the best approach for idempotent versus non-idempotent updates and the interaction with session transactions.
Should Mongoose add a retry middleware with exponential back-off and idempotency tokens? How would such middleware coexist with existing session transaction APIs? What performance overhead would it introduce for high-throughput workloads?
35275 reputation · 23 Jul 2020, 20:11 UTC
Mongoose does not provide a built-in retry middleware that guarantees at-most-once semantics for write operations. Instead, it delegates this responsibility to the underlying MongoDB Node.js driver via its "retryable writes" feature.
The MongoDB driver handles retries for specific write operations if the connection is a replica set or a sharded cluster and the connection string is configured correctly.
insertOne, updateOne, updateMany, deleteOne, and their bulk equivalents.retryWrites=true parameter. This feature has no effect on standalone MongoDB instances.majority (or an equivalent acknowledgment level).findAndModify with specific side effects, are not automatically retried by the driver.When you use Mongoose sessions and transactions, retryable writes are automatically disabled. This is because, if a transaction fails, the entire block must be retried as a single unit. To handle transient errors within transactions, you should use the driver's session.withTransaction() helper, which manages retrying the entire transaction logic automatically.
To verify that your environment is supporting retryable writes, follow these steps:
retryWrites=true and specifies a replica set (e.g., mongodb://host:27017/db?replicaSet=rs0&retryWrites=true).{ w: 'majority' } in the operation options to ensure the write is acknowledged.If your application requires more complex retry logic beyond what the driver provides, you should implement the following:
MongoNetworkError or MongoTimeoutError.updateOne with $set, or add a unique idempotencyKey field to your schema to guard against duplicates.session.withTransaction() to handle transaction-level retries.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.