You apply [DIP](https://codereview.stackexchange.com/q/148809/40367) when crossing a significant boundary. What's on either side doesn't matter. What matters is having a good reason to keep what's on one side from having a source code dependency on the other side. The magical thing DIP does is let you enforce that source code dependency rule while [allowing flow of control to go in and out of that boundary](https://softwareengineering.stackexchange.com/a/357066/131624) without resorting to using [return](https://softwareengineering.stackexchange.com/questions/365829/return-considered-harmful-can-code-be-functional-without-it). [![enter image description here][1]][1] When organized like this the assumption is that the inner stuff is more stable than the outer stuff. DIP lets you strip off the outer stuff and add new outer stuff without breaking the inner stuff. When you hear the words "higher" and "lower" understand those terms were developed when the style was to keep all inheritance arrows pointing up. These round diagrams make that metaphor a little meaningless. Here's a diagram that tries to give them meaning again: [![enter image description here][2]][2] This doesn't change your design at all. Just gives those words meaning again. [![enter image description here][3]][3] >And now the question: Would it be wise to apply DIP on all of these sub-services too? They are just internals of the service implementation and would not serve a purpose outside of the domain. I'll stick with the significant boundary rule here. Like anything, DIP can be over applied. I wouldn't be surprised to find every service that faced a significant boundary applying DIP. I would be surprised to find nests of DIP applied to every module in the service layer even if they don't face a significant boundary. Now that said, [circular dependencies](https://en.wikipedia.org/wiki/Circular_dependency) in source code are a special kind of hell. DIP can also be used to help avoid that. In all cases, be sure you understand why you're applying it. Don't just apply it cause someone told you to. Know why. >In other words: The official definition of DIP talks about high level and low level modules. Should all (sub-)services be considered one module or are they all separate modules? The rings in these diagrams depict layers not modules. Now sure, a layer could have only one module in it but it can easily have more. Here a layer is a bag of modules that are asked to follow the layers rules when they touch modules in a different layer. I can't speak for every author but I have heard Robert Martin explain module to mean object if you happen to be in an object oriented context. Modularization is an older philosophy of designing so parts are easy to remove and swap. You don't have to be object oriented to use modules. In an OOP context I'd expect one-to-many objects to make up a service and one-to-many services make up a layer (ring). While Onion, Hex, Ports, and Clean all amount to the same idea they each have their own vocabulary (designed to drive you to different books and blog posts). Because of that be careful when asking these questions because some words mean different things with different authors. [1]: https://i.sstatic.net/3WOuu.jpg [2]: https://i.sstatic.net/yzWRo.jpg [3]: https://i.sstatic.net/CiVH9.png