9 ms·
We use microservices at my workplace with a team of 5 and have since the beginning. From reading HN it seems like we may be the only small team to have benefitt
by evancordell 11y ago
We use microservices at my workplace with a team of 5 and have since the beginning. From reading HN it seems like we may be the only small team to have benefitted from the approach?
Some advantages that this article seems to ignore:
- Even with a small team, microservices allow us to make small iterative changes to services without touching other parts that are working as they should be.
- It's easier to find and patch bugs when they can be pinned down to a smaller codebase and fixed in isolation (most can be).
- Local development becomes easier - you can spin up just the services you need for the feature you're developing instead of the entire system.
- It's easier to get "up to speed" when you need to add a feature when you're working with small codebases (and often only need to touch one or two at a time).
- In our case we have three distinct sets of consumers: two fairly separate groups of end-users, and automated services (m2m). It's quite common for any issues we have to only affect one of those three sets of groups because they are largely isolated in different services.
That's not to say there haven't been some headaches, but I personally much prefer our service approach to a monolith. I really think the key is removing operational friction of working with services with tooling.
- falsedan 11y agoCongratulations! Those advantages you list are too big to ignore. I think the biggest stumbling block to SOA is that failure states have to be considered up-front, and the responsibility of concerns have to be designed into the system up-front. Degrees don't train you how to do this, so engineers stick with what they know will never fail (function calls). We've been experimenting with plugin-based architecture on some work projects, which force us to address separation of concerns (at least) while still keeping things in the same process.
- erikpukinskis 11y agoI wish engineers stuck with function calls! It's configuration files and objects that worry me.
- erichmond 11y agoWe've also benefitted from moving from a monolith to SOA-esque services. IMO, The thing that DHH is failing to mention is that Monoliths work great when your application looks something like Basecamp. Basecamp, while a great tool, is a "simple application". I don't mean it's not well built, I don't mean it's easy to build, I don't mean it was fast to build, but if you look at what it does, it's all vanilla stuff. Many other companies don't have the luxury of building apps that look like basecamp, and hence, our architectures are more complex. When he writes these kinds of articles, they always feel somewhat strawman-ish. At the end of the day, each software project has it's own unique requirements that will govern success. We got paid the nice salaries we do because it is up to our discretion to understand what is the most efficient architecture for what we are trying to solve.
- benjismith 11y agoJust curious what you mean by "if you look at what it does, it's all vanilla stuff". What would "non-vanilla stuff" look like? It's all just code, right?
- eric_h 11y agoI think he means "all the things that Rails handles well with default options/configurations"
- erichmond 11y agoIf you look at their feature list (https://basecamp.com/3/features https://basecamp.com/3/features) you see: - Message boards - comment threads. - Real-time chat/pings. - Automatic check-ins. - To-do lists. - Docs & file storage. - A centralized schedule Everything in this list sans real-time chat I would consider as low complexity, low volume and low velocity. It's basically request a view, hit a cache / db, display some data. Send an email now and again. Store some stuff on s3 now and again. There are lots of sites that have more complex feature sets then what basecamp does. Things like complex transcoding of media, real-time updates on their views, streaming of complex media types, need for near-real-time integration with 3rd party APIs, real-time bidding, real-time decision making, real-time analytics, etc etc etc. I want to be very clear that I am not criticizing Basecamp as a product. Simplicity is difficult to achieve in software and their product does a great job of doing most of what you need, and not much else. I based the software stack of the first company I founded on pre-1.0 rails monolith (mongrel had just been released), so I'm not even anti-monolith. I just think this particular post of his is entirely too simplistic and could lead younger software designers astray.
- matt_s 11y agoJust an observation that most of your advantages (4/5) are for the developers and their process of doing work. Choosing an architecture based on your ease of working seems fine, until you need to engineer that architecture to be fault-tolerant, scale, etc. (not saying what you are doing isn't fault-tolerant, etc.) That is where micro-services and distributing your architecture can introduce more failure points in the underlying infrastructure than with a monolith. It all depends on the problems being solved. My hope is people will architect a system based on the business needs as the primary factor and nice-to-haves would include making your work flow easier or trying new shiny things out.
- nfm 11y agoMost of those advantages aren't microservice specific - they're just a function of well factored code.
- deleted 11y ago[deleted]
- mikekchar 11y agoI'm perfectly willing to admit that I might be wrong here, but I don't really see a difference between a microservice approach and any other technique for abstracting out functionality. The only real difference is that you're using a network connection to enforce your abstraction. Back in the old days we use to use fork() and pipes for the same effect ;-) The thing is that if you don't require multi-processing, you are adding complexity to your solution that doesn't actually exist in the problem domain. Not only that, but you are forced to nail up your API between the services. My experience has been that one of the most common causes of complex code is premature subsystem decomposition. Before you have written much code, you design the subsystems and nail up an API. If it turns out that it doesn't fit, the opportunities for refactoring are practically zero. For some problems (and it could easily be the case for the problem you are working on), micro-services are really useful. Generally this happens when you require multi-processing. You create a service for each thing that requires a separate process and you build an API for communicating/coordinating those processes. You have to do that anyway, so it's a benefit to design the services (or whatever). Generally speaking, though, it is beneficial to delay subsystem decomposition as long as possible (but no longer). This allows you to change your internal APIs with low cost and acquire more requirements. This significantly reduces the risk that you have to major squirrelly work-arounds. If you don't need another process, then you often split out reuse libraries as soon as their API solidifies. If you do need other processes, then micro-services (or other similar approaches) can be introduced. On many teams, you often have developers who are incredibly confident that their initial designs will hold up over time. They are usually the person I am cursing when I show up 5-10 years later and have to wade through the jungle of bizarre work-arounds. For that reason, I tend to suggest to people that they should avoid micro services until they actually need them (which could very well be never).
- thedudemabry 11y agoI completely agree with your description of prematurely setting in stone the interface between two subsystems (which could be modules/libraries or independent processes.) If a chunk of functionality is identified as a candidate for a microservice, making an otherwise isolated library in the existing codebase is by far my preferred first step. It lets you live with the seam between the two systems for a while, adjust responsibilities and communication patterns cheaply as they reveal themselves as pain points, and delay or avoid paying whatever costs are associated with deploying a new microservice (which at my current company, at least, are non-zero.) Outside of a few examples where we've identified a simple and truly orthogonal set of responsibilities up-front for a new microservice (e.g. image resizing, push notification delivery) I have always regretted prematurely building a new service instead of extracting it from an existing codebase.
- macca321 11y agoIt's only 'easier to spin up just the services you need' if you assume there is a cost to spinning up everything.
- lmm 11y agoInteresting - very much not my experience. I think part of this is a question of typed languages (and structured build systems) vs. dynamic - with a typed language you can have strongly enforced separation between different parts of the codebase without needing to split them across a network connection. > Even with a small team, microservices allow us to make small iterative changes to services without touching other parts that are working as they should be. My experience is this should be the case anyway. Having the ability to "find usages" in the IDE, and lots of compile-time enforcement, gives me a lot of confidence that changes haven't affected anything unrelated. > It's easier to find and patch bugs when they can be pinned down to a smaller codebase and fixed in isolation (most can be). True but not something I find microservices help with. Any decent debugging/introspection tools are going to give you better information than a network sniffer. > Local development becomes easier - you can spin up just the services you need for the feature you're developing instead of the entire system. Don't forget the overhead of the network layer though. Particularly if you're using service discovery (and if not you have a config problem), I find running two or three microservices locally is heavier than running a monolith that contained the equivalent of ten of those services, and it's a fiddle to start the right ones during development. As long as the codebase remains a size that can be comfortably run on a single machine (and start up reasonably quickly, and all be open in the same IDE at the same time, and so on), it's much easier to just run the whole thing. > It's easier to get "up to speed" when you need to add a feature when you're working with small codebases (and often only need to touch one or two at a time). True up to a point - there's an intimidation factor, but I don't think it's actually any harder to understand a folder in a repo of ten folders than a repo that's separated from the other ten. And separating creates a barrier to organically expanding your understanding. If you have distinct build modules then project encapsulation is enforced just as much as for microservices.