somewhat serious

Beings & Daemons

An architecture I've "arrived" to on a few occasions is a daemon (née backend), with some sort of being (née frontend). The two communicate via message passing (i.e. messages), which can be an arbitrary string of bytes, as long as the two concur on the semantics of the bytes.

The daemon/being "pattern" is a specialization of client/server, one that does not leave the host machine.

An example on "the web":

  • A Web Worker is the daemon.
  • A browser client is the being.
  • They communicate via postMessage interface.

An example in the terminal:

  • A gradle (yuck) daemon is lauched and persists across builds.
  • A gradle build task (being) is attached to the daemon when run, and naturally when it dies, the daemon persists.
  • I don't know how they communicate (domain socket?), but they do.

An example terminal:

  • ghostty has a zig core, which is a daemon.
  • A per platform UI is the being.
  • Communicate via embedding (I think) the core at build time.

Some nice properties this pattern surfaces is daemons (depending on how they are built) are fairly portable and coordinate the tricky bits. They can also be leveraged as a means to wall off most side effects, or they can be used as a "pure function" (w/ a message receive being a function invocation). Daemons can also facilitate coordination between a set of beings with varying lifetimes.

This pattern is well known, and there are finally tools on the web (i.e. SharedWorker) to make building beings and daemons feasible. Especially if wasm is in the mix, a truly cross platform daemon may be built w/ zig, loaded in a worker, and plumbing setup to shuffle bytes between the two.