-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Another comment regarding "1.1 Structure your solutions by business components" #1266
Comments
Hi together, just a short update. I currently try to use the following concept:
Here an example for my import {
getActiveConfig,
getAllConfigs
} from '../business-logic/get-config-use-case';
export {
getActiveConfig,
getAllConfigs
}; And here my import { Config } from '@prisma/client';
import * as configCodeServer from '../../../config-service/entry-points/config-code-server';
export async function getActiveConfig(): Promise<Config> {
const config = await configCodeServer.getActiveConfig();
return config;
}
export async function getAllConfigs(): Promise<Config[]> {
const configs = await configCodeServer.getAllConfigs();
return configs;
} I can also write my code server a little more abstract like this: import { Config } from '@prisma/client';
import {
getActiveConfig,
getAllConfigs
} from '../business-logic/get-config-use-case';
export async function getActiveConfig(): Promise<Config> {
const config = await getActiveConfig();
return config;
}
export async function getAllConfigs(): Promise<Config[]> {
const configs = await getAllConfigs();
return configs;
} config-code-server.ts and config-client.ts look quite similar leading to redundancy (don't repeat yourself?!). But all in all it would be the same or perhaps even worse with microservices. I can use the client within another-service like this import * as ConfigClient from '../config-client'
async function anotherFunc(){
//...
const config = await ConfigClient.getActiveConfig();
//...
} How do you find this approach? I saw other approaches with messages being published to an (in memory or external) event bus. You can find information to this here: kamilgrzybek.com/blog/posts/modular-monolith-integration-styles I tried to implement the "direct call" approach. Here is also a great video on that topic. Modular Monolith - How to build one & lessons learned, from Milan Jovanovic |
Hi everyone! First, thank you so much for this resource that helps me not to forget important points while working on my platform that heavily relies on Node.js services.
I recognized that some of your best practices and especially your boilerplate code generator Practica "steer" people in the direction of microservices. I also thought of microservices while working on the initial system design of my platform, that will run on Google Cloud and Firebase. I decided against it because from my point of view it's too complex and also too expensive to start with. First, it is not feasible for me to run multiple DBs simultaneously. I cannot (or should not) scale them to zero and DBs are expensive to run 24/7. Second, while the latency caused by all the communication between the services via network isn't an issue for me (because I won't have thousands of reqs/second from the very beginning), the costs that come with exponential traffic might be an issue. I want to keep operational costs down. Furthermore it might be that I cannot scale services down to zero. It is more expensive to keep multiple services alive than just one. Third, the operational effort for deploying, running, monitoring and maintaining 10 instead of 1 or 2 services is immense for one or two people that need to handle thousands of other tasks, mostly not related to IT stuff but organization, acquisition, communication, support, etc. Sure, there are amazing tools and possibilities like CI/CD pipelines listening to small code changes and automatically deploying and starting new images; or infrastructure as code that can start the whole infrastructure at the press of a button. But learning these things takes hours, days, weeks, even years. As a guy who is starting up a project in his spare time, I cannot afford this. I need to keep things simple - at least at the beginning and until I can afford a team supporting me. (I don't want to go the common "startup" way that involves shiny marketing and shady contracts to get a few bucks so that I can hire someone who then needs to be coordinated and managed.)
But how can I "prepare" my system design, my structure and architecture so that it can grow naturally? What can I do now at the beginning so that I don't have to start over again if I want to enhance my system or if I want to replace a component with another? There are multiple reasons to go for microservices, or at least for a highly modular and decoupled design: As my startup grows, multiple people can work on different components without needing to understand the whole system or disturbing each other. When I identify some bottlenecks, a modular and loosely coupled system makes it easier to switch to another technology or programming language to optimize this specific component. Furthermore, microservices make it easy to scale components independently. So you can save lots of money because you don't have to multiply (= scale horizontally) the whole system.
But as I said: How can I manage the balancing act of keeping the system simple (easy to develop and to operate) and cheap on the one hand, but modular, expandable, and scalable on the other hand?
I would love to see such considerations and discussions in this repo. And I would like to get it started by sharing 2 (ugly) drafts I quickly prepared. The one picture shows a more decoupled microservices design with services communicating via network. All services have their own DB and clear interfaces so that other services can connect to them easily. The other picture shows a monolith with a component structure as you mentioned in best practice 1.1 Each component has its own schema and its own DB tables (in the same DB). The components cannot run independently (its a monolith or one docker container) but have clear interfaces so that other components can have "client functions" communicating with these interfaces.
I haven't had the time to write code examples but I will.
I really look forward to a valuable discussion. Thank you in advance!
Picture 1: Microservices decoupled
Picture 2: Easier design but with Microservices in mind
EDIT: I have to figure out if its possible to define a single DB with different Prisma schemas containing separate tables. Don't know if this is possible by design.
The text was updated successfully, but these errors were encountered: