---
title: "Comment by ZHE ZHANG on \"The Tri-Z Architecture: a Pattern for Layering ZIO Applications in Scala\" | Hashnode"
description: "Hello, I saw in your \"Beautiful Domain Logic\" slide that you discussed Event Sourcing, and it seems like events are written to both a database and a message que"
url: "https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1"
---

[Discussion](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731)

Comment [The Tri-Z Architecture: a Pattern for Layering ZIO Applications in Scala](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731)

[ZHE ZHANG](https://hashnode.com/@zhangjiji)

[Apr 29, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1)

Hello, I saw in your "Beautiful Domain Logic" slide that you discussed Event Sourcing, and it seems like events are written to both a database and a message queue like Kafka. My questions are: Is Event Sourcing actually used in games? Does the database encounter performance issues due to the large number of event records? How is Event Sourcing integrated with sharding (like Shardcake)?

[Pierre Ricadat](https://hashnode.com/@ghostdogpr)

[Apr 29, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-6810367cc1fa5d60260fa2b9)

We do use event sourcing and events are written to DB only (we use Kafka to trigger some workflows but with different events and much smaller scale). So our DB usage is very write-heavy indeed. We use CockroachDB which makes it quite easily to scale. Event sourcing is independent from Shardcake: Shardcake provides us actors/entities that are distributed over our servers and addressable by ID, then in each entity we use event sourcing to manage the entity state (via snapshots/journals). So we use both but they are not directly connected.

[ZHE ZHANG](https://hashnode.com/@zhangjiji)

[Apr 29, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-6810e3bf082d6436d67b163d)

I did see akka-persistent-cockroachdb in devsister's GitHub repository, but I assume this was used before migrating away from Akka, correct? Is the actual event sourcing interaction still using Akka / Pekko, or is it implemented separately? Also, are there any recommended ZIO libraries for interacting with CockroachDB?

[ZHE ZHANG](https://hashnode.com/@zhangjiji)

[May 8, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-681c71dbc97b52c5e1a91787)

Regarding state reads, I imagine they happen in `shardcake`'s behavior. Then, the `ZPure DSL` is run, generating events. These events are sent to the DB. After successful DB operations, the in-memory state is updated using the same event handler lifted via `lift`. Is my description accurate? If `STM` is involved, it might be harder to conceptualize, as those cross-module events would also need to be atomically committed to the DB. Could you please advise if there are any good libraries for `CockroachDB`? [Pierre Ricadat](https://hashnode.com/@ghostdogpr)

[Pierre Ricadat](https://hashnode.com/@ghostdogpr)

[May 8, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-681c7574aadd6478cc7915ca)

Right, we are not using Akka persistence and instead use our own code. We're just using [github.com/typelevel/doobie](https://github.com/typelevel/doobie) to communicate with the database.

We don't use STM in this part of the code actually, it's all one big state object in memory. When we load an actor, we load the latest snapshot and journals, replay those to have the latest state in memory. Then we serve reads and writes from that.

When we need a "fast access" to some data without loading the actor, we have some view tables in the database that are updated via Kafka: after the state is updated and saved in DB we publish some Kafka messages and a separate component reads those and update the views.

[ZHE ZHANG](https://hashnode.com/@zhangjiji)

[May 8, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-681c78ed061ee51da5de0fe7)

I'm also curious, if we use Kubernetes rolling updates, will the database read pressure be very high when the in-memory actor state is rebuilt? [Pierre Ricadat](https://hashnode.com/@ghostdogpr)

[Pierre Ricadat](https://hashnode.com/@ghostdogpr)

[May 9, 2025](https://hashnode.com/posts/the-tri-z-architecture-a-pattern-for-layering-zio-applications-in-scala/66b07c222ac672d4672fe731/comment/68101fa388ebcac2ef43f1c1#reply-681d459dd3a3a23a3443d218)

In our case it has never been a problem (since rolling updates start pods sequentially the pressure is not that high).
