Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS with REST APIs

I am building a REST service over CQRS using EventSourcing to distribute changes to my domain across services. I have the REST service up and running, with a POST endpoint for creating the initial model and then a series of PATCH endpoints to change the model. Each end-point has a command associated with it that the client sends as a Content-Type parameter. For example, Content-Type=application/json;domain-command=create-project. I have the following end-points for creating a Project record on my task/project management service.

  • api.foo.com/project
    • Verb: POST
    • Command: create-project
    • What it does: Inserts a new model in the event store with some default values set
  • api.foo.com/project/{projectId}
    • Verb: PATCH
    • Command: rename-project
    • What it does: Inserts a project-renamed event into the event store with the new project name.
  • api.foo.com/project/{projectId}
    • Verb: PATCH
    • Command: reschedule-project
    • What it does: Inserts a project-rescheduled event into the event store with the new project due date.
  • api.foo.com/project/{projectId}
    • Verb: PATCH
    • Command: set-project-status
    • What it does: Inserts a project-status-changed event into the event store with the new project status (Active, Planning, Archived etc).
  • api.foo.com/project/{projectId}
    • Verb: DELETE
    • Command: delete-project
    • What it does: Inserts a project-deleted event into the event store

Traditionally in a REST service you would offer a PUT endpoint so the record could be replaced. I'm not sure how that works in the event-sourcing + CQRS pattern. Would I only ever use POST and PATCH verbs?

I was concerned I was to granular and that every field didn't need a command associated with it. A PUT endpoint could be used to replace pieces. My concern though was that the event store would get out of sync so I just stuck with PATCH endpoints. Is this level of granularity typical? For a model with 6 properties on it I have 5 commands to adjust the properties of the model.

like image 571
Johnathon Sullinger Avatar asked Sep 17 '25 07:09

Johnathon Sullinger


1 Answers

This is a common question that we get a lot of the time when helping developers getting started with CQRS/ES. We need to acknowledge that applying REST in a pure way is a really bad match for DDD/CQRS since the intention of the commands are not explicitly expressed in the verbs GET/POST/PUT/PATCH/DELETE (even though you can use content-type like you did). Also the C/R-side of the system are definitely different resources in a CQRS-system which does not match up with REST.

However, to use HTTP to provide an API for a CQRS/ES system is very practical.

We usually only use POST for sending commands, to either a /commands endpoint or to endpoints with the name of the command, i.e /commands/create-project. It's all about how strict you want to be. In this case we embed the command type in the payload or as a content-type.

However, it is all a matter of what matches the tech stack better and what you choose here usually does not make or break the solution. The more important part is usually to create a good domain model and get the whole team onboard with this way of thinking.

Good luck!

like image 162
Mattias Holmqvist Avatar answered Sep 19 '25 21:09

Mattias Holmqvist