Dev Overflow Logo

Dev Overflow

Global search

Search across questions, answers, users and tags.

Loading...
save

MongoDB transactions: do I need them for a two-collection write?

clock icon

asked 3 months ago

message icon

2

eye icon

526

When someone posts a question I insert into questions and then into tagquestions, and increment a counter on tags. If the second write fails I get orphaned data. Are transactions the right answer, or is that over-engineering for MongoDB?

2 Answers

Multi-document transactions are the right answer, and they are unremarkable on a replica set now:

1const session = await mongoose.startSession()
2try {
3 await session.withTransaction(async () => {
4 const [question] = await Question.create([doc], { session })
5 await TagQuestion.insertMany(links, { session })
6 await Tag.bulkWrite(ops, { session })
7 })
8} finally {
9 await session.endSession()
10}
1const session = await mongoose.startSession()
2try {
3 await session.withTransaction(async () => {
4 const [question] = await Question.create([doc], { session })
5 await TagQuestion.insertMany(links, { session })
6 await Tag.bulkWrite(ops, { session })
7 })
8} finally {
9 await session.endSession()
10}

withTransaction also retries on transient errors, which hand-rolled commit/abort blocks usually forget.

Two caveats: they require a replica set (Atlas gives you one; a bare local mongod does not), and they are more expensive than single-document writes — so use them where atomicity actually matters, not everywhere.

If you cannot use transactions, the fallback is to make the operation idempotent and reconcile — write the question first, then have a background job repair missing tag links. Strictly worse, but it is what you do on a sharded setup where the transaction cost is real.

1

of 1

Write your answer here

Introduce the problem and expand on what you've put in the title.

Top Questions