Stream guidance

Using EventStore for “command” messaging, I could have 1 command stream for an entire BC, so that commands for all aggregates are in a single stream. Assume that in this case, I have hundreds of thousands of aggregate instances in this BC.

I was thinking about this, there could also be a command stream per aggregate. The command handler would likely subscribe to a category projection to handle all of these commands, but I’m thinking a benefit here would be increased write throughput for commands. Also I could do competing consumers on the category projection.

Any suggestions on using one approach over the other (1 command stream per aggregate type vs. 1 command stream per aggregate instance)?

"I was thinking about this, there could also be a command stream per
aggregate. The command handler would likely subscribe to a category
projection to handle all of these commands, but I'm thinking a benefit
here would be increased write throughput for commands. Also I could do
competing consumers on the category projection."

This would get LOWER write throughput as you need the category
projection enabled :slight_smile:

Writing to a single stream is probably fine (its linearized internally anyways).

Yes competing works on $ce-whatever streams providing you have permissions.

Ah, I see. I suppose that having a single command stream per BC is simpler as well.

OTOH for a slightly different use-case, lets say I have events for a multi-tenant application with ~50 tenants, and I need to parse commands for these tenants in order to know how I should react to them (there isn’t explicit data to use as a key). Here I think I’d have a stream per tenant, and do one catch-up connection (or persistent/competing) per stream in my handler-processes. I think I could have another stream, say “tenants”, where a “tenantAdded” event would cause a processor to connect to that stream.

This way I can parallelize writes to the tenant streams when ordering matters (write for tenant-A doesn’t have to wait for tenant B-write).

How well would this scale? This means a lot of TCP connections to EventStore (tenants*handler-processes). I seem to recall a planned feature that exposes the “fromStreams” functionality in the .NET ClientAPI - maybe this could work more efficiently.

You keep talking about parallelizing writes but internally event store
will linearize them anyways.

Again a single stream could be used just blocking when ordering is
needed on your own.

So, with the multi-tenant example, this could be one stream, but block writes per tenant, assuming that I want to preserve ordering per tenant. Thanks, that makes perfect sense.

Out of curiosity however, if I did want to have a stream per tenant, do you suspect that it would be problematic to have many subscriptions (catch-up or persistent) from .NET clients? I’m guessing that I wouldn’t want to have many subscriptions (40-50) originating from a single connection / .NET client, but I’m thinking this could allow me to easily utilize in-memory caches and also shard read-models.

"Out of curiosity however, if I did want to have a stream per tenant,
do you suspect that it would be problematic to have many subscriptions
(catch-up or persistent) from .NET clients? I'm guessing that I
wouldn't want to have many subscriptions (40-50) originating from a
single connection / .NET client, but I'm thinking this could allow me
to easily utilize in-memory caches and also shard read-models."

Call all the streams ingress-tenant then read from $ce-ingress if you want ^^