16 ms·
Modules vs Microservices
- jsiepkes 10y agoWe build a modular system based on Java with OSGi. It served us well but now we feel we have reached the limits of such a system and are looking at a more microservice based approach. For example a modular system is not going to help you when a module is misbehaving since the whole thing still runs in the same process (JVM in our case). If someone introduces a resource leak in some trivial module the whole thing still comes down.
- SanderMak 10y agoExactly, that's one of the tradeoffs discussed in the article (author here). Another pattern that might work, which I didn't include in the article, is to scale-out the modular application (assuming it's 'stateless') into several clusters. Each node in the clusters still has the whole modular application. However, each cluster will be responsible for handling a certain part of the API. Then, put a load-balancer/API gateway in front that can route different functional parts of your API to different clusters. Scale up the individual clusters as required by load. Even though all nodes contain all modules, depending on which cluster they're in, only a certain subset of modules really takes up CPU cycles. There's still no node-to-node communication necessary, since all nodes contain all logic. Certainly not a pattern that's always applicable, but I've used it with success several times for webapps with REST backends.
- jsiepkes 10y agoFor us scaling was never an issue; We did the stateless scale-out thing. Even solving statefull is relatively easy (at least in Java) with solutions like Hazelcast. The main drawback is there are usually only a few services in your monolith that are required to scale out. But you have to deploy the entire thing when scaling out. As for OSGi, OSGi is complex; I dare to say that the complexity of OSGi rivals that of a microservice setup. If I had a nickle for every classloader issue I debugged... ORM was especially fun (For example wrote this piece way back: http://www.datanucleus.org/products/datanucleus/jdo/osgi.html http://www.datanucleus.org/products/datanucleus/jdo/osgi.htm... ). But I must admit that I don't think we could have created (and maintained) such a large modular application without OSGi. Debugging itself is also way more complex. When an issue arises you spent a lot more time tracking down which module is misbehaving. Even though we had inserted lot's of probes (which ended up in graphite) and log statements (which ended up in graylog) to counter that. In my experience writing smaller, simpler applications (which I acknowledge also have their own complexity with distributed debugging) are still easier to understand then an modularized application.
- SanderMak 10y agoI'm with you on the complexity of OSGi, though some of the complexity plainly arises because it truly forces you to modularise vs. just winging it. In that regard, the new Java 9 module system has less of the service dynamics and classloading tricks going on. Very curious to see how the community will pick up the new module system.
- twic 10y agoThis is a cool pattern which deserves to be more well-known. I once worked on an e-commerce system where we deployed many copies of a monolith. Most were serving user requests. Two were running scheduled jobs. One was something to do with a distributed cache (this was a while ago). One was processing events off a queue. Having one codebase and one binary made development and releasing easy. Having multiple roles made production simpler to understand and more reliable (i think). Another time, i worked on business web app. Again, one codebase, one binary, three instances serving users, two instances serving a data export API, and some number running scheduled jobs. When the API went down - which it often did - users were not affected. That company also tried splitting services out of that monolith; one was pretty successful, but one was a chronic failure, because so many features involved coordinated changes to both codebases.
- mickronome 10y agoTo get high availability every system need to be able to hand over processing to another instance of itself in some way. Modular or micro-service make no real difference here, except that a bigger collection of modules in a single JVM will take a bit longer to startup, but if you really can't periodically restart your service to reclaim lost resources due to 24/7 requirements, you will need to have several JVM instances serving the same service anyway. This makes start-up times mostly irrelevant since any decent load balancer will handle seamless handover almost trivially. Microservices is a rather resource expensive solution to modules bringing the JVM down for whatever reason. Usually the right thing to do is to decrease amount of state in the application, think in microservices without HTTP and within the JVM, and finally: Run a a bunch of small JVM's instead of one large. The upside of this approach is that when/if you need to migrate some modules to actual microservices, you have already made part of the work, already tested that you can run multiple instances of the same service, and all without the significantly increased operational and development complexity of microservices. Microservices is good where it really is the only option - eg. heterogeneous technology stacks and subsystems with different release schedules. Simulating the grid/web of microservices including network errors like timeouts, latency and dropped connections in a petri-net (or similar) simulation tool can be a rather eye opening experience if the set of services isn't trivial. The set of weird behaviours a network of services can exhibit is staggering, even without a single line of code.
- deleted 10y ago[deleted]
- mpfundstein 10y agodo you have any reading material/links/software regarding petri-net simulations?
- mickronome 10y agoI'll see what I have when I get back to my computer. In the mean time, the magic words to find interesting things are something like "colored timed petri-net" A lot of it will probably be about logistics, but sending a shipment and calling a service is mostly the same thing, might have to squint a bit. Toolwise, there are the ProM tools (www.promtools.org), which although they are mostly for mining process networks from logs can also be used for simulation and analysis. A bit of a warning though: It's a rather strange piece of software, not very stable (for me), but it has a ton of modules related to process mining and simulation. Lots of the petri-net stuff available is generally a bit dated, as although it's a useful, and quite simple formalism, it only ever appears to have caught on in somewhat niche areas.
- CptMauli 10y agoIt is sad, to see this as the only comment on OSGi, which actually provides an elegant solution for modularization. I agree that tracking down problematic modules is difficult. And OOM Exceptions (due to leaks) are actually the only serious problem where we run into problems during runtime. On the other hand, even in these cases its often enough to just restart the single OSGi service (if you know which one). For NeoSCADA it was definitely the right choice. We have servers running uninterrupted for months (if not years). And to be able to hotpatch a library on the fly, is really really great (although seldomly used).
- bluejekyll 10y agoI used to make this argument. I'm not so convinced anymore. Much of this modularity can be achieved now, split you libraries into two, one for APIs and the other for Implementations. Then in your build, only include the API libraries as dependencies, and include both at runtime. It doesn't enforce runtime modularity, but it's generally good enough. Why this isn't great, it encourages monolithic mindset. A huge benefit to microservices is that they are small! This means means that you have releases that are faster per service, build times that are faster per service, code that can be more easily reasoned about. The author is correct that it introduces expensive cross service calls, so you do need to be thoughtful on your boundaries, but what you end up getting is simpler on a per instance basis. You don't need to become devops experts; there are plenty of options for deployment that handles a lot of this: heroku, gae, beanstalk. Hell, there's even still available to you for your own D.C., though I'd argue that if you're running in your own D.C. then you should think very hard on why that's important to your business (even if it's very large). The earlier you have microservice architecture built into your stack, the easier it is to continue on that path, once you're monolithic, it's a huge amount of work to go back the other way.
- discreteevent 10y agoA huge benefit to modules is that they are small! This means means that you have releases that are faster per module, build times that are faster per module, code that can be more easily reasoned about. The earlier you have modular architecture built into your stack, the easier it is to continue on that path, once you're monolithic, it's a huge amount of work to go back the other way.
- bluejekyll 10y agoHave you considered what will happen when you're application has reached a muti-gig deployment? Where you have static resources commingled with business logic? Where you have rendering blended with DB access? Modular systems are theoretically as good as SOA or microservices, but in practice they are not. Failure can not be isolataed as easily, when there is a problem in the system, the entire thing crashes. Also to your point; is that a single repo, or multi-repo source control system? In a single repo system your build and testing cycle becomes longer and longer for the entire service, regardless he size of changes, you have to deploy the entire thing. Every successful business with a monolithic deployment, regardless of repo structure, ends up in the same place (based on my experience): a large unwieldy beast, maintained by dozens or hundreds, or thousands of engineers, who each have limited knowledge of the runtime. It becomes slow, hard to deploy, hard to test, hard to make changes. Microservices/SOA does not alleviate the need to good design, but it doesn't allow for the above to be true on a perservice basis, shortening turnaround for response to issues and deploying new features, it is better.
- vojant 10y agoI co-founded startup 6 months ago, since day 1 we use micro-services. For us the biggest benefit was that at the begin we could hire people knowing different programming languages (we managed to build a team of 5 in 3-4 weeks) and they could build a small parts of the system communicating via http/RabbitMQ. Downside is that we had to have a CI&CD from day one and it costs us some resources. I am not saying microservices are cure for everything and of course there is a place for well maintained monoliths but I find that even for smaller teams micro-services can be just easier than monolith.
- mylons 10y agoI don't think using micro-services from day 1 is a wise use of resources. What if one of your engineers, who probably owns an entire service, quits? And it's in Haskell because she felt like it?
- verletx64 10y agoSurely the CTO factors this into signing off on any decision on what the engineers use to build the service. You can have an ecosystem comprised of different languages absolutely, but that doesn't become "Billing Automation is built in Idris because Brian wanted to try it out".
- staticassertion 10y agoThis is a totally nutty scenario. Microservices are not "do whatever you want!" - they give you the freedom to choose your stack. It is obviously still a business decision to choose Haskell and you've got other problems if developers are building things in random languages that they feel like using without a larger discussion. The issue here isn't Haskell it's ownership and process.
- amorphid 10y agoNutty or not, it happens. I was a Ruby dev and was asked to work on a Scala app. I could contribute to Ruby stuff quite nicely, and could hardly figure out how to compile the Scala app. Trade-offs...
- tabeth 10y agoshouldn't the goal be to do whatever provides the most value and builds your product or business the fastest? if you waste time with a microservice architecture where you could've done more, faster with a monolithic app that seems like a poor use of time.
- akamaozu 10y ago"If I had 8 hours to chop down a tree, I'd spend the first 6 sharpening my axe" - Abraham Lincoln If you delivered the initial thing in 4 weeks vs 8 but you'd spend way more in future development and developer time, would you say you made the right decision? To put it another way, delivering the wrong thing faster doesn't make it any more right.
- tabeth 10y agocouldn't you just as easily say you build the wrong thing in more time with your hypothetical increase in future speed, but you go out of business because you never have any customers? what you're saying is the right thing, if you have unlimited money.
- 100k 10y agoI know microservices are successful in many organizations but one downside I've experienced from the microservices hype is starting an application with microservices. It's very difficult to get the system boundaries correct while you're still iterating on core functionality, and if you get it wrong you're in a world of pain. Refactoring becomes very hard and performance suffers from unnecessary network overhead. Deployment is harder. Coordination is harder. Developers can't run the whole system locally. Testing is harder. Basically, if you don't have a very well defined interface between components, it's going to hurt. I would not recommend starting with a microservices architecture. Build a modular, well-factored application and split out pieces if they need to be scaled separately or there are other compelling benefits of a microservice. To quote Kris Jenkins: This is your return type: Int This is your return type on microservices: IO (Logger (Either HttpError Int)) Microservices: Know the risks. https://twitter.com/krisajenkins/status/762901550696194048 https://twitter.com/krisajenkins/status/762901550696194048
- nawitus 10y ago"Developers can't run the whole system locally." Developers should be able to run the whole system locally.
- 100k 10y agoI agree. In the system I'm currently working on, they can't. I think it would be possible to implement, but no one has been able to take the time (or, perhaps sees the value in it). (OTOH, I kind of doubt developers at Google or Facebook run the whole thing locally, so there must be some kind of end state for this.)
- nawitus 10y agoIf the alternative to microservices is a monolith, and you can run the monolith locally, then logically microservices can also be run locally. If it's difficult to run all the microservices locally then that's just a sign of weak tooling.
- tannhaeuser 10y agoBeginning in 2003, and until the height of the SOA craze around 2010, the Service Component Architecture (SCA) was seen as the holy grail of service integration. It encompassed both local/in-process (or in-JVM) as well as networked services (SOAP and REST), was polyglot in that it defined API bindings for native, Java, and even PHP and Cobol, could access external services, and was still quite practical. For those needing it, it also supported authorization and transaction policies and protocols. When commercial interest in SOA middleware products dropped sharply, further standardization of version 1.1 slowed down, and Oracle, sitting on the SCA board, voted down all specs that had been worked on without further explanation. To this day I still haven't understood what makes microservices different from SOA in a technical sense. I can get that the term SOA was probably burnt at some point, but if there's a real lesson to be learned from SOA failures, I'd really like to know. Maybe SOA was seen as too complex because it addressed some of the harder problems such as transaction and authorization protocols/boundaries, BPM, etc. upfront?
- troygoode 10y agoMicroservices is to SOA as "JSON over HTTP" APIs are to REST APIs. Fundamentally the same goals but with a focus more on being a general description of a "style" rather than a specification for how it should be implemented. This is a double-edged sword of course...
- jwilliams 10y agoFor a while I was consulting a lot around SOA - particularly around the IBM stack, which was one of the biggest SOA evangelists in the early days. SOA was too complex for sure, but it wasn't just that it was complex. It's that complexity didn't actually deliver the return. Part of the issue was the way SOA was sold. You buy a BPM or a Rules Engine and suddenly you unlock all this value and you can compose things on the fly -- Rules Engines were particularly bad in this respect. Business users were told they'd be able to tweak rules on the fly. This was never a reality. Then you get outright hits in terms of complexity. Those BPM systems with two-phase commit were monsters. In fact they were so complex it was _more_ likely to fail. When in the vast majority of cases, actual failure rates were rare and easily handled by a reconciliation process. So the tech never really matched the need. On top of that, the consultants cost a fortune. Instead of a few test environments, you needed 7. Managing test data and rollout to end-users became a nightmare... And even then, as the technology wasn't mature, you'd hit hurdles very late. Dismal production performance was a common one. It's a bit sad. A really interesting set of ideas and technologies - but really poorly sold and way past the hype to deliver. It's equally true of related technologies like CORBA.
- sebringj 10y agoI even found using submodules in git was really helpful as well even though it wasn't a module per say. For example in Mongo, I have models in node.js and it is really simple to share the model in every node project across the org as mongo models contain schema and validation etc.
- Walkman 10y ago"The modularized monolith can be scaled horizontally as well, but you scale out all modules together." That's not exactly true. Yes you probably have to ship the whole monolith, but who said that you also have to get traffic for all the parts? For example you have /users/ and /books/. You can configure your nodes to only serve /users/ and configure different (maybe more) nodes to serve /books/. The code sits there but who cares?
- 100k 10y agoWe did this at my last gig. The application was monolithic[1] but ran in multiple environments: web application, API, admin, backend workers. It worked quite well. The one downside is we had to load all the code (it was Rails) so processes took more RAM than strictly necessary. But sharing data models across all these services was pretty easy. [1] There were a few separate services, for example a documentation CMS.
- SanderMak 10y agoAbsolutely, also see my other reply along these same lines: https://news.ycombinator.com/item?id=13960837 https://news.ycombinator.com/item?id=13960837
- mooreds 10y agoI found this a refreshing article that have a nuanced view of different solutions. Also I was glad it acknowledged that different solutions make sense at different scales and times in an organization's life.
- Xcelerate 10y agoIn my experience, the biggest obstructions to modularity are the "unknown unknowns". I can't tell you how many times I've been trying to set up some software where it turns out the installation was looking for file ABC in directory XYZ even though the documentation wasn't up to date and listed directory EFG (or nothing at all). Also, environment variables (i.e., global variables) are a pain and should be eliminated altogether. What would replace them? I'm not sure, but any random idea has got to be an improvement of some sort over the current system. Docker alleviates the environment hell problem somewhat, so it's easy to set up a bunch of contained microservices that aren't going to fall apart when the global environment changes. We need more research into the complexity of programming patterns. The same patterns and anti-patterns keep popping up under different names in slightly different forms.
- Nomentatus 10y agoSpeaking of random ideas: dump the globals into functions (one function per global) - that's right a dumb single-variable function. You can't monitor or pop an assert on a variable, but you can put slap asserts inside a stub function, etc. Plus you know a function ain't local. Globals are such poison that the minor inefficiency created by converting a few globals to functions is usually meaningless. I begin to think that we need a richer vocabulary to address "complexity." To analyse it into various forms, (some of which are likely to be beneficial.) Separating code into lumps means more lumps; but fewer dependencies, more known absence of dependency... We keep using one word "complexity" to point to various things. Distinguishing between Complex(opposite of 'simple') and 'complicated' (opposite of 'easy') is a start I suppose, but I can't help thinking there are more careful distinctions that could be made.
- AtticusTheGreat 10y agoI don't have much ideology behind going with microservices vs. monolith, but what we've done on some recent projects is organize our code into modules that only communicate with each other through a narrow and well defined boundary layer. If we need to split a module out into a separate service, then it isn't nearly as much work to split it out later. One of the practical issues we've had with microservices that need to interact with each other in real time is ensuring a consistent state across systems. For example, let's say I need to change the status of an object and afterwards, call a separate service to change state there as well. What happens if the call fails in some way? You can't just run all of this inside a single database transaction anymore. Now you have to design your code to deal with several potential failure points and edge cases, which adds complexity. The other consideration is all calls to a service should be idempotent if possible. It makes coding from the client side a lot easier if you can just fire off a call multiple times (in case of local or remote failure) and not have to worry about state. Just some of my thoughts, since this stuff has been on my plate recently.
- SanderMak 10y agoGreat observation, and exactly what I meant with the modular alternative in this article. When you can 'get away' with such an architecture, it makes a lot of things simpler.
- aaronblohowiak 10y agoIf you have transactions that have to span multiple modules, I'd argue they are too commingled
- pm90 10y agoOne solution is to use a distributed key value store (like etcd) to coordinate tasks. Kubernetes does that (AFAIK); you should definitely check that out.
- brandur 10y agoTransactions certainly make it easier to maintain global consistency, but one possible contradiction with the above is that if your modules are sharing transactions, then your boundaries are no longer narrow and well defined. By definition, your entire database and all its internal workings are now part of the interface. This is one problem that I've observed with all the monoliths I've worked on. Because modules are colocated and sharing a database is easy, eventually somebody will do it (even if it wasn't originally intended), and you get lots of ostensibly modular code intertwined with other modules in non-obvious and subtly problematic ways.
- the_arun 10y agoFew advantages for Microservices over modules is - performance of one module impacting other modules. 1. Say one module is running slow, that will impact entire application. 2. If we want to push code for one module, we need to push code for entire application. So there is no deployment isolation. 3. We have to have all the modules written in same programming language and same version of the programming language. Hence there is no clear path for upgrading version of programming language. Micro Services addresses all these assuming we deploy Micro Services separating the services (including data). But the tradeoff is a bit of complexity and latency for the benefit of complete isolation and independence.
- icebraining 10y ago1. Say one module is running slow, that will impact entire application. Why? Unless you're doing something silly like running the whole service on a single process+thread, the other workers should still respond just fine while the slow module is crunching away. 2. If we want to push code for one module, we need to push code for entire application. So there is no deployment isolation. Yes and no. In what sense does that worry you? You can still ship only changes to one module, using version control. And you can still do a gradual deployment, avoiding downtime. The only thing you can't easily do is take down a whole module while keeping the rest of the application running.
- the_arun 10y ago1. Because infrastructure resources are shared - like CPU & memory 2. If all the modules are managed by same team, yes you are right. If we want each module to be managed by one pizza scrum team, we need need deployment isolation to avoid churns. Don't you think so?
- ajessup 10y agoRecently I've seen a few folks use protobufs within parts of a monolith as a mechanism to enforce a strongly typed interface between components. This helps define a contract between teams without the overhead of a distributed system.
- mackross 10y agogRPC can do the same and define the service calls.
- z3t4 10y agoa micro service should be independent.
- rapala 10y agoIf a micro service is independent it makes no calls to other micro services. Thus the system has a single service and that service is a monolith. Contradiction, thus a micro service cannot be independent.
- z3t4 10y agoLets say ycombinator.com was news.y, www.y and apply.y, all served from the same "monolith". And they decided to make them into separate micro-services ... The best way is to make them all independent!
- migueloller 10y agoHis comments with regards to the lack of compile time checking of the interfaces between microservices couldn't help me but think of GraphQL. Using GraphQL as the layer between microservices could alleviate this issue. Specially if the usual "deprecate, don't version" approach of GraphQL is followed. Normally GraphQL is talked about within the context of user facing applications interacting with servers but it could be quite useful for strongly typed machine to machine communication. We already use GraphQL for our client facing API. We're going to start rolling out microservices at our startup and I think we'll use it for communication between microservices as well.
- phamilton 10y agoI'd recommend taking a look at gRPC.
- migueloller 10y agoJust took a look at gRPC. Thanks for the great recommendation!
- techwizrd 10y agoAt the start-up I currently work for, I designed the system to be composed of microservices (with Swagger/OpenAPI), even when it might've been easier to write modules, for scalability reasons. Before I was brought on as the first engineer, we had a series of contractors build a poorly architected monolith that had issues scaling. Microservices have enabled us to independently scale different parts of the service as load changes. It's also forced a very strong separation of concerns. My main complaints are that we've run into various instances where we need to access some data in a different service, so we stuff it into some object so that the next service can pull it from the DB. However this is a solvable implementation issue. The other complaints I have are that monitoring and profiling are much more involved. Additionally, setting up a new service can be painful if you don't have a template. Overall, we've had a good experience with microservices and it's enabled us to deploy faster and scale simpler.
- dasil003 10y agoI've advocated for this approach before, I think it's definitely true that a single code base is an optimal place work out early architectural decisions so you can optimize the interfaces and separation before committing to the overhead of multiple repos and deploy stacks. One of the challenges, though, is making sure the whole team understands the vision and doesn't violate the intended separations. Working primarily in Rails, I've found it to be pretty terrible in this regard, both due to ruby's global namespace, but also just because there are no conventions to properly separate app-level modules (Rails Engines are a second-class citizen). Django is significantly better since it gives you apps as first-class citizens, and because of Python's explicit module import, but even still you can quickly end up with a ball of mud if you're not careful.
- aryehof 10y agoIsn't a microservice just a small application behind a network boundary? Moving what might be a big ball of mud into smaller ones?
- bg4 10y agoThis is why I tend to build microservices that implement a bounded context. Then compose those different APIs, as necessary, to implement the public facing API. I don't need granular level services, it places too much burden on operations, but I still get the separation of context, concerns and 'anti-corruption' layers that I'm looking for in my design.
- im_down_w_otp 10y agogen_server:start_link/3 The original microservice :-)
- cpeterso 10y ago> Modules are natural units for code-ownership as well. I read a snarky blog post a few years ago entitled "Blame-Oriented Software Design". It described legitimate design patterns that software developers in a Dilbert corporate environment can use to deflect blame and extra work caused by others' shoddy code. Examples include well-defined module boundaries, strongly-typed APIs, and extensive assertions and logging enabled in production code. Unfortunately, I can no longer find this blog post, but I chuckle about it often enough that sometimes I consider rewriting what I remember of it myself. :)
- keithnz 10y agoBe interested in if anyone has much experience in using an Actor type model instead of microservices. Things like Akka/.net / orleans / Erlangs OTP etc
- shitgoose 10y agoI don't have a TV so somehow I missed the moment when "monolith" became a dirty word.
- closeparen 10y agoFor my employer, the whole point of microservices is separate deploys. When we had hundreds of engineers committing on the monolith, a bad change in one out of the few dozen commits in a given day's upgrade could require rolling the whole thing back. Now each service deploys (usually) one or two commits at a time, completely understood by the person who clicks the "upgrade' button. People working on unrelated code don't need to block each other's release velocity. More disciplined interfaces could have solved the spaghetti problem, but lots of small services that a few people have absolute power over can move a lot faster than an integration/release process shared by thousands.
- deleted 10y ago[deleted]
- sreque 10y agoI think the article is missing a key value of microservices, or at least smaller services: service ownership. With a monolith, who is on call for the service when something goes wrong? How does that person find an appropriate person to diagnose the issue in one of the 100 libraries included in the monolith? What does the monolith dashboard look like? The great thing about small services is that a team developing a service can own it from top to bottom: including: 1) being responsible for metrics, alarms, dashboards, and everything else required to monitor the service 2) being oncall for the service and getting directly paged when their are problems And of course, there are other social/organizational problems with a monolith, another example being deployments. I want to deploy my new feature but I'm blocked because someone introduced a bug in some unrelated library that's clogging the entire pipeline. Or, I have to release my feature according to the deployment schedule of the monolith, which may not make sense for my team. With smaller services, a team can own its own deployment pipeline and decide when it wants to deploy. A third organizational benefit of smaller services comes process separation. GC'ed languages work really hard to help developers pretend that memory is free, but memory is still a finite shared resource and it only takes one misbehaving module to cause the whole process to start stalling in large GC pauses. With smaller services you get process separation which makes the problem much more tenable. And of course there are other exhaustible shared resources like threads, and file descriptors. At the end of the day, I prefer smaller services because I like the social organization where a company consists of agile, autonomous teams owning their own services. I feel a monolith service actively discourages that and leads to social organizations that are less productive and successful.
- abrookewood 10y agoAll fair points, but I think people ignore the challenges associated with microservices: much more complex to debug (which service is failing); inter-service latency (things run much faster on a single box); VM/instance sprawl (because every service should run on its own host x redundancy x multiple environments); increased costs (see vm sprawl). I still think the advantages outweigh the disadvantages, but they definitely come at a cost.
- eloff 10y agoThose are organizational concerns that you're conflating with microservices vs monolith. They're tangential. I see no reason why you can't assign team responsibility to individual modules vs microservices. You can collect metrics for both modules and microservices and publish them in a dashboard. Alarms and monitoring are probably unnecessary at the module level in most cases - you'd just do it once for the whole monolith.
- tybit 10y agoFor those of you happy with your use of micrsoservices, how many microservices does your team handle? I don't mind microservices but I definitely think my company has taken it too far, for my team of 5 we have ~25 separate components/deployments which make up ~12 microservices. It makes it impossible to keep track of each service and be familiar with idiosyncrasies in each project.
- eloff 10y agoI've worked on both types of projects and I would never choose microservices over monolith if presented the option. Rather, I agree with the author that proper separation into documented modules gives most of the benefits from microservices without any of the numerous drawbacks. Microservices seriously increase the operational overhead. They increase the hardware expenses. They increase service latency through round trip times and unnecessary work. They increase the code complexity through unneeded serialization/deserialization and REST calls vs plain old function calls. They make debugging a lot harder. They give you all the pain of distributed systems and networking when all you previously needed was a function call. With Go (and many other statically typed languages) you get proper modules that can't reach into the private implementation of other modules (even with reflection.) They can't have import cycles. The compiler will take care of alerting you when an API changes in an incompatible way. Likely all your modules will share a backend database(s) so you need to take care to use the public interface of the responsible module rather than reach around behind its back with direct queries - but that's a solvable organizational problem. I wonder sometimes if the microservices craze isn't trying to find a technical solution to human problems that would be better dealt with via communication and creating solid organizational practices. Like team A doesn't trust team B and rather than work out a common set of norms and rules they just start using microservices to bypass dealing with the problem all together.
- euske 10y agoWatching a discussion like this really make me wonder this: what is a module, anyway? There are obviously varying aspects of modularity, such as: * different code locations (e.g. functions) * different namespaces (e.g. libraries / Python modules) * different release cycles / distribution models (e.g. ES6/Java modules in this sense?) * different OSes / languages / security models (e.g. microservices?) Seems like people (including myself) are confused by putting these in a one-dimensional spectrum. The reality is probably never that simple.