So how would you im­ple­ment clas­si­cal, ACID trans­ac­tions across REST mi­croser­vices?

Dis­claimer

If you are a REST purist then you may not like the idea, but sev­er­al prag­ma­tist de­vel­op­ers have been ask­ing us how to im­ple­ment clas­si­cal ACID trans­ac­tions for their REST sys­tems. After all, split­ting up that mono­lith is nice but there's still data in­volved...

In­tro­duc­tion

Some of you may know our TCC for com­pen­sa­tion-based REST trans­ac­tions for reser­va­tion-style in­ter­ac­tions. It's nice and loose­ly cou­pled, but it not a per­fect fit for sce­nar­ios that would like to use a clas­si­cal roll­back in­stead of com­pen­sa­tion. This post presents an al­ter­na­tive de­sign, one that we are cur­rent­ly work­ing on here at Atomikos.

We'll re­fine the spec­i­fi­ca­tion in­cre­men­tal­ly in the rest of this post, so the con­cepts are eas­i­er to di­gest.

In­tro­duc­ing the ac­tors in­volved

We'll use the fol­low­ing ac­tors and re­spon­si­bil­i­ties:

REST ap­pli­ca­tion

Imag­ine a (com­pos­ite) REST ap­pli­ca­tion that:

  • Co-or­di­nates the over­all work­flow
  • Calls a num­ber of par­tic­i­pant ser­vices
  • Com­mits (or rolls back) all of the par­tic­i­pant ser­vices' work via a co­or­di­na­tor ser­vice (as de­scribed be­low).

Par­tic­i­pant ser­vice

A par­tic­i­pant ser­vice is re­al­ly a mi­croser­vice that:

  • Creates a lo­cal ACID trans­ac­tion when it is in­voked
  • Per­forms lo­cal data­base work
  • Keeps the trans­ac­tion open at the end of the in­vo­ca­tion for lat­er com­mit by the REST ap­pli­ca­tion (as de­scribed be­low).

Co­or­di­na­tor ser­vice

The co­or­di­na­tor ser­vice is a spe­cialised util­i­ty ser­vice that co­or­di­nates two-phase com­mit across sev­er­al par­tic­i­pant ser­vices. It also per­forms log­ging and re­cov­ery in case of fail­ures and/or restart. More de­tails are be­low...

The min­i­mal use case: com­mit or roll­back REST mi­croser­vices to­geth­er

The min­i­mal use case is re­al­ly the most ba­sic thing one could do in this con­text: two or more mi­croser­vice calls are com­mit­ted or rolled back to­geth­er. It goes like this:

  1. The REST ap­pli­ca­tion goes about and calls any num­ber of par­tic­i­pant ser­vices.
  2. Each par­tic­i­pant ser­vice re­turns (as part of its re­sponse) AcidPar­tic­i­pan­tLink in­for­ma­tion: ba­si­cal­ly a URI where the trans­ac­tion can be com­mit­ted.
  3. The REST ap­pli­ca­tion col­lects all the AcidPar­tic­i­pan­tLinks as it pro­ceeds in the over­all "trans­ac­tion" log­ic.
  4. The REST ap­pli­ca­tion then asks the co­or­di­na­tor ser­vice to com­mit (or, al­ter­na­tive­ly, roll­back) ALL the rel­e­vant AcidPar­tic­i­pan­tLinks of its work.

More elab­o­rate use case: re­peat­ed in­vo­ca­tions can share the same locks

The pre­vi­ous sce­nario works, but re­peat­ed in­vo­ca­tions of the same par­tic­i­pant will use dif­fer­ent lo­cal ACID trans­ac­tions, mean­ing they can­not see/ac­cess the same data in the data­base. There is no lock shar­ing among sub­se­quent in­vo­ca­tions. In some cas­es this may be de­sir­able, and this can be done as fol­lows:

  1. The REST ap­pli­ca­tion calls a par­tic­i­pant ser­vice for the first time and gets an AcidPar­tic­i­pan­tLink back.
  2. The REST ap­pli­ca­tion ex­tracts the par­tic­i­pant's trans­ac­tion iden­ti­fi­er (in­clud­ed in the AcidPar­tic­i­pan­tLink).
  3. The REST ap­pli­ca­tion can now call the par­tic­i­pant ser­vice a sec­ond time, with the trans­ac­tion iden­ti­fi­er as an ar­gu­ment of the call.
  4. The par­tic­i­pant ser­vice de­tects the ex­ist­ing trans­ac­tion iden­ti­fi­er and al­lows the call to "join" the ex­ist­ing trans­ac­tion.

Every­thing else works like in the pre­vi­ous sce­nario.

Ad­vanced use case: a ser­vice shar­ing locks of the caller in a shared data­base

In some cas­es it may be de­sir­able for the par­tic­i­pant ser­vice to join a trans­ac­tion that ex­ists at the caller side, no­tably if they ac­cess some shared data­base. The de­tails of this will be worked out lat­er, so keep check­ing back for more!

Up­date: this has now been im­ple­ment­ed as out­lined here: Trans­ac­tion­al REST mi­croser­vices with Atomikos
RSS

Comments

Add a comment

Corporate Information

Atomikos Corporate Headquarters
Hoveniersstraat, 39/1, 2800
Mechelen, Belgium

Contact Us

Copyright 2026 Atomikos BVBA | Our Privacy Policy
By using this site you agree to our cookies. More info. That's Fine