artem

artem

Hi all

I am learning CQRS and Commanded by doing a project (so main point is learning), I’ve got to the point where it is already doing something useful on my laptop: you type a news article and then it uses ChatGPT for crafting some clever posts about it + you can tune the response with supposedly cool UI.

Now I want to make it public and let people play with it for free, but within some limits so I don’t get bankrupt on a hobby project (say, some 20-50 generations for user per month or per whole user lifetime) and.. how do you do it in CQRS? :slight_smile:

Non-CQRS ways
I come from Java/SpringBoot world so a relatively natural way for me would be to have some sort of credits field in the customer or user object. Then before doing something expensive (ChatGPT generation in this case) I’d check if there are credits available and decrease them in the same transaction. If generation fails, then some fail handler may or may not reuse credit back.

Ways for CQRS and specifically commanded
As everything in CQRS is eventually consistent, does it mean that I need to “book” some credits, make it somehow possible to monitor when the “booking” is completed (via some projection with a booking request id?) and only then do a request?

Or is possible to rely on Commanded’s strong consistency (or maybe it’s enough to specify option returning: aggregate_state when dispatching) and once dispatch has happened I can already know if the credits were enough or not.

Or am I missing some other obvious options? Like is it possibly common for exactly “credit checks” kind of use cases live outside CQRS so that DB transactions could be used for consistency protections and access serialization?

Again, my main point here is learning (though I still want to open project to public), so I’ll highly appreciate any hints and ideas, especially if ever did anything like that in CQRS.

P.S.
Even though it’s mostly self-education project almost invented just so I could have a real use case to play with CQRS, there is still some reasoning for exactly CQRS. My main technical motivation is about separating read-write models so I could have as many and as convenient read models as I like. Access serialization and consistency are way less important for me in this particular case.

Showing Posts 1 to 1

byu

byu

Caveat: I’m a major beginner in EventSourcing and CQRS.

What about something like the following?

  1. Manage an Event Stream (aggregate) per User per Refresh Period (month, year, all time).
    • eg generation-account-bob-202402
    • This tracks not just the count, but the lifecycle of each generation request.
      • pending, completed, failed to complete, rejected.
    • Also can have event that indicates the number of allowed credits.
  2. Use a SubmitGenerationCommand that includes
    • request identifier
    • request payload/details about the generation TBD
  3. Handling the SubmitGenerationCommand can emit Events
    • GenerationSubmittedEvent – with request identifier
    • GenerationRequestRejectedEvent – with details such as:
      • max pending requests limit reached
      • max credits reached.
  4. An Event Handler or Process Manager can watch for GenerationSubmittedEvent and then issue commands or execute API requests?
    • Then somehow events get back into the “generation-accounts” stream that would indicate success or failure?
  5. And more Event Handlers would watch for Success/Failure events to then send message to update the “conversation”?

Basically, requests go into a “rate limiter” aggregate for that user-period. The Events of Submitted/Completed/Failed/Rejected requests allow the single aggregate to track the used credits count, pending credits such that used credits + pending <= allowed credits ? and can reject requests over the limit?

And follow-on Event Handlers will eventual consistently process (succeed or fail) the submitted requests?

The above uses patterns:

  • Closing the Books – like accounting, so we can reset the user’s credit each period
  • Many small streams, instead of big streams – A small stream of data for each user-time-period instead of a single stream for the user of all time.
  • Write Ahead Pattern – we are writing the “request submitted” event to hold the pending place, then a Completion/Failed event to confirm the credit usage

We avoid:

  • Reservation Pattern (book keeping) – because if the credit is reserved/booked, that reservation has an expiration because that ticket may never have been used/completed… And even then, the generation processor that receives the ticket and executes for a GenerationCompleted response MAY race condition with the ExpirationEvent.

[edit]: Here’s a suggested video that also talks about how to do different kinds of “business transactions” that spans multiple streams:

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New
dillonoconnor
Is there any way to avoid the Hologram compiler running when using iex? It seems like the front-end code could potentially be disregarded...
New

Other Trending Topics Top

mikehostetler
ReqLLM - Composable LLM client built on Req Release v1.27.0 · Hex v1.27.0 I’m especially excited about this release: ReqLLM now support...
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews