D4no0

D4no0

To commanded or not to?

I want to build a system where I want to to execute some jobs periodically (about once per day). One of the requirements of the system is to store all the results of those tasks as history, so they can be used later for analytics and KPIs.

My previous approach to this kind of problem was to use real-time databases (usually influxDB) and send measurements directly from the application, however in this case it seems that there will be large amount of data and I’m not sure whether those types of databases can handle this kind of load.

Some time ago I stumbled CQRS/ES concept and it seemed like a good idea to use this as an alternative to measurements. Having no previous experience with this kind of systems, I wondered if someone from you, who worked with library like commanded could advice me wether it is a good idea to use this tool, or it would be smarter to just use a primitive approach, like storing the data manually with queries, as I don’t have requirements to use previous events for projections (at least for now).

In addition to this, I would like to know if you prefer to be using Postgres to store events, or it is much better to use something like EventStoreDB.

Marked As Solved

hst337

hst337

That’s a great question.

There are several things I think that will help you decide

  1. Event Sourcing and operations history for analytics are very different approaches, though they might seem similar. Event Sourcing pattern works only when you store the command/event in casually ordered chain before you actually apply this operation to read or write model. This approach makes sure that the

    1. Each event and command has happened in exactly the same order as it is stored in Event Store. This is extremely useful for any money-related problem or for distributed transactions with very critical data
    2. It is easy to rollback in time and replay some events from exact time to find a bug or inconsistency or security breach or whatever

    On the other hand, analytics are not required to have casual or linear order. Most of analytical data can be stored after the request was processed. Analytical data can be lost, since it is not critical and data loss just decreases quality of the analytics. Most of the analytical data can be aggregated. Analytical storages do not need to have ACID and append-only properties (which are required for Event Stores), and they can be column oriented like Clickhouse.

  2. Commanded linearizes all events and commands in a single process and then stores them in the Event Store. This is clearly a bottleneck for heavily loaded systems, but it is very useful for systems where linear order of commands/events is required.

Given the two points above, you don’t need Event Sourcing and therefore you don’t need Commanded.

I’d recommend time series or OLAP databases such as Clickhouse. This choice depends on the kinds of analytics you want to gather.

Also Liked

nivertech

nivertech

IMO, Command Sourcing/Replay is necessary for proper Audit Trail and for recording/replaying realistic test scenarios, instead of writing integration tests manually.

I think the simplest solution is for every command to emit a special audit trail event with the command in the payload, or maybe Commanded has some hooks or middleware that allows this to be done without boilerplate code?


Links relevant to this discussion:

Event Sourcing vs Command Sourcing (2013)

Jean Paliès - How video games taught me event sourcing

Game Replay

Command Sourcing

Command Sourcing vs Event Sourcing

dimitarvp

dimitarvp

Unless you need load balancing or any other multi-application-server scenario then you might as well go with DuckDB. It’s basically the equivalent of SQLite for OLAP needs.

dimitarvp

dimitarvp

Oh by the way, here’s a link to clickhouse-local.

beamologist

beamologist

I don’t want to end up in some strange polemic back-and-forth,
Unless you also store the reason why a command fails, I still don’t see the point of keeping track of them in a persistence store… (in the end, there is still this thing called “logs”, right?)…
Also, I am not sure if I fully agree with “the reality is that most often they [commands] don’t fail”…it reminds me of the statement “The network is always available.”

It is called an aggregate because it aggregates the list of facts that represent the (volatile) state, quite a technical artifact that is usually not so useful when communicating with business people. For that audience, I tend to use “business process” or “behavior”.
Also, the phrase “Would you want us to built your new system based on hopes, rather than facts?”, usually sticks :slight_smile:

hst337

hst337

Unfortunately, I don’t have any experience with analytics in Postgres, but if I was solving this task, I would take a look at how commanded stores it’s events.

If events are written in huge amounts and read very rarely in export fashion (read all at once), I would

  1. Batch data on the client as much as possible.
  2. Write one huge batch into one row with postgresql or client-side compression

However, it might also depend on the kind of analytics you’re gathering. If it answers questions like “how many times in a second on average/maximum/minimum”, I would take a look at OLAP approach. If it anwsers questions like “what and when did the user do in our program”, I would take a look at time series approach

Plus, Postgres might require some tuning for write-heavy workloads like WAL tuning and setting fillfactor to 100%


https://medium.com/nerd-for-tech/postgres-fillfactor-baf3117aca0a

Where Next?

Popular in Questions Top

gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement