Backend code is too noun-oriented

Backend code often gets organized around entities without anyone really deciding to do it.

OrderService
PaymentService
InvoiceService

A table appears, then comes the repository, service, controller, DTO, mapper.

It is everywhere, so it stops looking like a choice.

Then behavior gets buried inside noun-shaped buckets.

OrderService
├── OrderRepository
├── PaymentService
├── InventoryService
├── PricingService
├── ShippingService
├── NotificationService
└── AuditService

That is not one thing.

It is several workflows grouped together because they all touch an order.

I prefer making the behavior explicit.

PlaceOrder
├── CalculateOrderPrice
├── AuthorizePayment
├── ReserveInventory
├── CheckOrderFraud
└── SaveOrder
CancelOrder
├── LoadOrder
├── RefundPayment
├── ReleaseInventory
└── SendCancellationNotice

Now the code says what the application does.

The dependencies say exactly what each use case needs.

This is not against OOP.

PlaceOrder, AuthorizePayment, policies, entities, and workflows can all be objects.

The problem is not objects. The problem is treating database entities as the default architecture.

That works fine for CRUD.

In complex domains, it hides rules, workflows, ownership, and change boundaries behind generic services.

The part I find interesting is how unquestioned this pattern is.

Who has seen this done well around use cases or capabilities?

And how did you convince a team with strong egos that this was better than another round of SomethingService?

reddit.com
u/im_caeus — 2 days ago

Looking for a TypeScript stream/async workflow library with native backpressure and resource safety

I’m looking for a TypeScript library for async streams/workflows where backpressure, cancellation, and resource safety are native to the abstraction rather than something I have to bolt on manually.

The kind of semantics I’m after:

  • Pull-based or demand-aware execution
  • Backpressure by default
  • Safe resource handling: acquire/use/release, finalizers, cleanup on cancellation/error
  • Good composition for async producers and consumers
  • Works naturally with producers like "() => Promise<T>"
  • Strong TypeScript ergonomics
  • Usable in real Node projects, not just as a toy abstraction

The thing that pushed me here is that RxJS does not seem to model this the way I want. For example, if I create a stream from a "() => Promise<T>" and use "repeat()", it can keep producing without naturally accounting for whether the downstream consumer is slow. That makes sense for RxJS’s push/observable model, but I’m looking for something with different default semantics.

For reference, the kind of model I have in mind is closer to Scala’s "fs2" or "ZIO Streams", but I’m not looking for a Scala clone. I’m looking for the closest practical equivalent in the TypeScript ecosystem.

I’m aware of a few possible directions: Effect, async iterators, Node streams, Web Streams, IxJS, Highland, etc. I’m trying to understand which ones actually have good out-of-the-box semantics for this, especially in production TypeScript code.

What are people using for this?

reddit.com
u/im_caeus — 1 month ago

Type-safe TypeScript DI container with lazy async initialization and CommonJS support?

I’m looking for a TypeScript DI/container library or pattern that fits these constraints:

  1. Type-safe registration and resolution
  2. Async initialization support
  3. CommonJS compatibility
  4. Not eagerly initialized by default

The last two are important.

I don’t want something that behaves like NestJS by default, where the application/container eagerly initializes the whole graph at startup. I’d prefer lazy/on-demand initialization, where services are created only when needed, but where async setup is still modeled cleanly.

The async part matters because some services need setup before use: DB connections, config loading, SDK clients, caches, etc. Ideally there would also be a lifecycle story for shutdown/disposal.

Type-safety-wise, I’m thinking of something in the direction of "typed-inject", where tokens/dependencies are statically tracked, although I’d prefer stronger ergonomics/typing if possible.

Something roughly in this spirit:


const container = createContainer() .provide(Config) .provide(Database) .provide(UserRepository)

const repo = await container.get(UserRepository) // typed, lazily initialized

I’ve seen libraries like Inversify, tsyringe, Awilix, Typed Inject, and Effect Layers mentioned, but I’m trying to understand which options actually hold up when async initialization, lazy resolution, and CJS output are non-negotiable.

What are people using for this in real projects?

reddit.com
u/im_caeus — 1 month ago