Real World Micro Services
micro.dev
micro.dev
Disagree with this core premise.
The biggest problems we face are that every developer is coached into believing everything they make needs to be unicorn scale and quality, that everything they build should conform to impractical levels of scrutiny and long-termism and that it is unavoidable for even basic development needs to have incredibly high levels of complexity in code / build / release tooling.
Microservices are just the latest weapon in furthering this agenda for the good of a tiny minority of people who value indulging their time and business costs in esoteric software philosophy goals.
> Most devs are rebuilding identical software stacks to serve a very small different business layer product.
The problem is plainly because we don't recognize that the "Identical Business layer" does not exist. On the surface they seem identical but then each has its own features/prerequisites/peculiarities etc. And you end up with having to fight that "reusable framework" to handle all this because to be reusable it has to stay generic enough and the more generic something is the more useless it is for the concreate problem and more time consuming it is to reuse it.
In the golden era of Web Services the moto was to make reusable software same as electricity is reusable through standards (just plug in your device) forgetting that Electricity is reusable only because it doesn't really do anything. All implementation of the useful work is in the device you plug. And what's more these devices now are forced to work on non efficient standards, Hey I need just 2W of power to work but to interface with the Reusable thing I must waste 5w power to conversion. Fortunately we still don't have that kind of reusability in Software and hope we will never have to.
It's not perfect, but it saves an amazing amount of duplicated work. The problem is getting to be that the framework is getting big enough that people new to the company don't always know what's in it, and accidentally end up implementing something that already existed. We're still working on a solution to this.
If you ever solve it, please let me know! Discoverability is hard.
Many years ago, we were trying to introduce a form of peer review process for the group I worked in, and we did a few exercises to see how well it worked in practice. I will always remember the striking result that around 50% of the issues raised during the first code review experiment were about reimplementing functionality that was already available somewhere else that the developer just hadn’t come across before.
I find this problem often happens with large standard libraries. Languages from Python to Haskell come with huge numbers of useful data structures and algorithms out of the box that can reduce a handful of lines of boilerplate to a one-liner with a standard name if you just use the provided tool. But of course, first you need to know that that tool exists, or at least have enough intuition that it might/should exist to check for it.
The best practical solution I’ve encountered so far is Haskell’s, where the strong culture around static typing means data structures and other important patterns tend to have explicit and well-known names, and where we have Hoogle, which is essentially a search engine that looks for known functions based on their input and output types. Need a function that checks if a given value is in a list but can’t remember what it’s called? Just search for `[a] -> a -> Bool` (Haskell syntax for a function taking a list of some type and a single value of that type and returning true/false) and you’ll soon find `elem`. Oh, and `notElem`. And their respective generalisations that work on types other than just lists, too.
In today’s world full of package managers and external dependencies and remote APIs and microeverythings, it feels like standardising this kind of search tool could have enormous benefits. It’s a problem that will always be difficult to automate away with tools given the fundamental limitations, but developers who know their own intent when writing code could certainly save a lot of time and make that code shorter and safer if we moved in this direction.
do we _really_ need to rewrite that every time we start a project in a different language that doesn't already have an implementation?
Or, could it be loaded/used via a service or other resource that's made accessible in some language agnostic way?
They are building upon Netflix offerings.
Sorry, but really not getting what this is achieving/solving?
It also provides opportunities to do far more interesting things with the data when you have enough users at scale e.g predicting demand, caching data, etc.
Man I feel old and stupid, but really still not got it any further :( You made it even worse now.. "lives on the network.. without updating thousand binaries" - huh what, how?
You sound a bit like Urbit btw, not sure if appropriate ref though.
Everything is defined as protobuf interfaces, which is a standard used by Google and everyone else now that gRPC is so dominant. So the idea is, define the API in protobuf, code generate and implement the handlers for it. The service can be called by other services on the platform using that code generation and then an API Gateway, which Micro provides can be used to call services externally using the same format but using HTTP/JSON.
To take that even further, M3O (m3o.com) codifies protobuf to openapi specs and then generates client libraries on top. You can see some of that in https://github.com/m3o/m3o.
> The biggest problems we face are that every developer is coached into believing everything they make needs to be unicorn scale and quality
I kind of disagree with both of these statements. Reusability/DRY/etc. is just a useful technique or pattern. If you can do it, cool. If it's not worth it, factoring in complexity and cost, carry on.
Building something stable, reliable, and dependable, which is what I take "unicorn scale" to mean, is not necessary, it is simply good engineering. If you're thinking this is necessary for every project, you're not necessarily a bad developer, just a specialist, and the only real problem is if you don't realize that.
Software is a blend of engineering, art, and craft. Knowing what mix the current problem calls for is really the core pillar of being an effective developer. Too much engineering in your prototype and you've undermined it's flexibility. Too much craft in your production service and you've created a maintenance nightmare. Not enough art in your API and nobody wants to use it.
The challenge is that assessing outcomes is very contextual. There are teams that will be successful with a completely overengineered system built with what seemed like an unrealistic toolkit, and there will be teams that fail with an overengineered system and seemingly better toolset and team. For example, I'm aware of pharma teams using K8s and Svelte for small apps when a Django or .NET app would be sufficient.
We also got to centralize the read cache memory pool in the frontend, so each backend service is not potentially caching duplicate stuff, saving on memory across the org.
* Not always true of course
I understand where the author comes from. You want to use tools developed in company instead of being cut off when you leave.
Stack Overflow regularly bragged about how their eight servers and a few MSSQL replicas were basically always in a coma, even at peak hours. That's just good engineering.
Microservices themselves solve nothing out of the box.
1. Trust. I need a strong vendor or community behind third party code which will issue security updates, have transparent roadmap that I understand and agree with and good paid licensing and support business model. It’s a high bar, but having some control over supply chain is important.
2. Architecture. Domain-specific services that integrate with some APIs are middleware: either I have to build some other middleware to integrate them with loose coupling, or I have to accept their integration contracts as a basis for my solution architecture. Both don’t look good to me.
3. Cost. If the problem is generic enough, why I should take only the code but spend money on DevOps to deploy it? No-code SaaS today is great and it’s all-in-one, being cost-efficient simply because it eliminates expensive internal maintenance effort. And it’s commodity today, there are often many alternatives for some problems, so vendor lock-in isn’t as scary as it was before.
In relation to being a CTO of a small startup, yea OSS maintainer risk is tough. You want to use projects that are used by hundreds of companies and actively maintained. In my case, I am the primary maintainer and it's used for a cloud service called M3O - https://m3o.com. I think it will take a while before we're in a place to warrant more buy in but my hope is eventually it'll get there or at the very least people will come to use the APIs serviced by M3O.
On architecture, I mean you're quite literally talking about software "build vs buy" tradeoffs for the entirety of all software you ever write. In this case, do I integrate something else or write it myself. I think that comes down to the same assessment of whether you should offload to some other piece of software versus your own. When it comes to domain specific services this is always tough yet we see the adoption of the likes of Twilio for SMS, Sendgrid for Email and Stripe for Payments so I'd argue we're getting closer to blurring the lines now.
On cost, you can use the hosted offering - https://m3o.com - but at this point the reason I'm sharing the open source services is really because I think that adoption curve to a cloud service takes a lot longer especially with domain specific services. I would argue these services while on the surface appear a commodity, the development time and integration cost of using bespoke independent APIs or services has a much higher cost. Everyone internally ends up writing proxy/shims to SaaS products to try eliminate this risk for themselves. I just think we should standardise a lot of our business logic service consumption.
message QueryRequest { repeated Filter filters = 1; }
message QueryResponse { repeated Record records = 1; }
message Filter { string field = 1; string op = 2; string value = 3; }
Something like that. I think otherwise a majority of issues really become clear through use, so those using the services tend to see where the pitfalls are or where they can contribute. It's harder to do that without context and arguably less enjoyable for the person contributing as they're not seeing that change in whatever they're doing.
This doesn't seem at all accurate.
CPAN is from 1995.
But reuse - no. I don't remember ever pulling a dependency from GitHub (stupid question, but is that even possible?), although I've been doing that for many years from Maven, NuGet, npm, CPAN.
* constantly creating branches even for small changes because merges became so magical (e.g. in comparison with SVN)
* code reviews because they had nice visual tooling built-in
In my opinion reusing libraries came from the OSS movement in general. There were SourceForge&Co before github.
Code reviews... maybe? Outside of OSS you're probably right about them being less prevalent. Arguably a backwards step compared to XP though!
I would be more in favour of having option to point every service at a rabbitmq queue to listen on and have a format of message that containes the delivery report queue to use when email is sent to notify rest of the system.
And here we come to conclusion, everyone has his own idea. This is who it is hard to make really good reusable micro services unless each of them becomes not so micro.
Nice that people try but i'm still in the camp of building from lego bricks provided in libs and creating my own microservices in a way I see them interconnect fit for given project. It might be protobuf, http or qeueue systems.
The other thing, as another commenter pointed out, is that these are nanoservices; I find it really difficult to imagine a situation where you would ever need 10x of one service for 1x of another, for example. It's a litmus test for microservices: do they have to scale independently.
A lot of these just interface with an external service doing the heavy lifting, so the performance requirements for each of these is low; little to no value in running them on separate, independently scalable VMs.
Other things are more full fledged e.g a db service that provides a http interface on top of postgres, or the user service with email verification and the app service that does hosting on top of Google cloud run.
In the DNS case is basically DNS over HTTP which might not be useful to you since you can implement it but to someone who doesn't coslde it's useful.
Image service is storage and serving on top of micro which arguably yea you can do elsewhere and the wrapper to imagemagick you can do yourself but we've found there's a ton of people who just don't want to reimplement this logic.
This is the most succint argument against kubernetes I've heard yet.
You mean like string concatenation? Come on man. As far as evolution goes, that’s what semantic versioning is for.
It would be cool if it were possible to pipe the output of one these services into the input of another. Like how pipes work in Unix.
I eventually switched to a code monolith running in a segmented way with temporal.io, where I have libraries of activities which run in different nodes. You might be interested in their product.
Who is your provider for SMS?
Can we add our own APIs to M3O?
But really: much of this is either a) stuff that should be a library, even in a microservice ecosystem or b) could just be a static file (like the list of holidays).
I haven't dug into it at all yet, but at a glance it looks like it's aiming to do something similar to what Go kit (https://gokit.io/) or Finagle (https://twitter.github.io/finagle/) does, where it gives you a nice abstraction for defining your "service" and then handles all the supplementary aspects (service discovery, serialization, retry/circuit breaker logic, rate limiting, hooks for logging, tracing, and metrics, etc) so you don't have to build those from scratch every time.
I don't know if any of those other frameworks could really be considered very "successful" outside the original organizations they were built for (it seems like the industry has bet more on service meshes and API gateway products), but I'd probably be more inclined to start with one of them than making a new framework.
Micro is more of an all encompassing platform that addresses not just writing code but running, consuming it, securing it. I've been using it in production for 3-4 years now after a lot of pure OSS development. Still as others are saying it may never reach its true potential without the backing of a big vendor.
Take the crypto microservice. Someone says, e.g. "I notice that it doesn't support Argon2". If it doesn't, I can't use it, I would need to write my own library. Arguments ensue about you don't need Argon2 or "why not contribute the change to the library?". Maybe the maintainer doesn't want to accept the PR because they don't think the library needs it or they are not sure that the quality is high enough to accept. The library gets forked internally and the fork takes on a life of its own.
I don't want to be negative but my experience is that people have a certain way of doing things and unless these services do it in that way, people won't live them.
There are other ways in which they wouldn't be able to be reused like if people don't know how to build/deploy Go or they are only looking for something simple but the fully featured libraries are too hard to understand.
Maybe having something is better than nothing but I think the saying is something like, "in trying to be all things to all people, you end up being nothing to any of them".
I really hope I am wrong though because the amount of duplicate work in the world depresses me as an engineer!
All this is, is putting you at a disadvantage, vs just a package that isn't hosted on its own.
I'm tired of seeing wrong theorems applied and sold as something good when in reality its bad.
Why this makes the top page of HN is beyond me
why?
The "answer" microservice says: "Instant answers to any question" / "Ask a question and get an instant answer". Okay? Like, is this a service that I would have to back with my own knowledgebase? In which case this is just a service that accepts questions and serves answers? Why would this need its own service then?
The "address" microservice says: "Lookup UK addresses by postcode. Simply provide a valid postcode and get a full list of addresses". Why is this not called "uk-address" then? Or can it be modified for arbitrary locations? Does it handle when new addresses are created? Can it do validation?
How much demand is there for a "joke" microservice? And I think it shows a lack of professionalism to seed such a microservice with something like this: https://github.com/micro/services/blob/master/joke/examples....
It runs on software that's also real https://github.com/micro/micro
It's hosted on a cloud platform with real customers https://m3o.com
Toby Clemson's infodeck on Martin Fowler's site has a lot of information about testing microservices: https://martinfowler.com/articles/microservice-testing/
"Testing in production" doesn't necessarily mean "Test only in production". Cindy Sridharan has a nice article about the nuances involved: https://copyconstruct.medium.com/testing-in-production-the-s...
A lot of people will likely not want to wait behind the open-source standardization effort on how to extend the service definitions for an API like email sending or file reading, e.g., does the file ACL go in the generic metadata map [2]?
There probably could be value for service definitions and a proxy that allow you to directly access a proprietary API but with a transport of your choice like gRPC which only happen to offer REST/JSON. But trying to come up with a standard API without collaboration among the largest of industry players will likely go virtually unused.
[1] https://en.wikipedia.org/wiki/Swagger_(software) [2] https://github.com/m3o/m3o/blob/fb7eb42512e4c7db49ab03da0b47...
Or are we supposed to clone all the repos and host ourselves? Do they all have the same deployment cicds?
A grouping of open source repos is useful. But there is a reason why I pay companies for “freely available” services when I have my own revenue on the line.
Uhhh, pardon me? We were sharing code, even packaged libs, long before GitHub or even Git.
For instance, the assumption that everyone wants to use an HTTP request for every little query and deploy, maintain, and debug dozens of live services. Don't buy into the microservices thing? Then you can't reuse this code.
One of the APIs is for SMS. Any idea which provider is being used for these SMSs?
Also, I see some similarities with Rapid API. Another API sharing platform. It would be cool if other devs can add their own APIs to Micro's platform to make some extra loot.
A lack of agility coupled with an inability to reuse code from embedded/edge project to another. We have also chosen microservices to apply it to the embedded domain with our open-source project Luos, but there is still a long way to go.
But this is looking far more polished - excellent. I am inspired.
Good luck !
I kindly ask you to stop and keep your code proprietary and hidden, for the sake and salary of the average software engineer.
Personally I feel like if we can open source building blocks that become the foundations for our development then we can build more interesting things on top e.g you're not going to build redis, postgres, etc again, but what are the things we build on top of them? We have a lot of open source infrastructure but not much in higher level categories. One day we'll get there, but it takes multiple people trying time and time again before we get there.
Countless other software developers and me build those things. If what I am currently building becomes available for free, as usable open source, I might lose my job. The company that let me go can increase their revenue and reduce their costs. You gain nothing, maybe some clout and fame.
Open source is harmful to the average developer. After years of this, we'd just be happy to reinvent StringUtils, EmailValidator and FileUtils classes every few years and take home our decent salaries.
I think now is the time for us to start moving beyond just open source infrastructure and into open source services. Yes as developers that means the things we write will change, yes some of us will have to reskill and learn new things but that's also just how evolution works in engineering. Whether its code or whether its cars, we, the current generation will be displaced by automation and large scale solutions.
Your business might want to reconsider its specialization, if all of your "hidden" work often gets built by a student in their free time, on the other side of the world, for free.
Times every 2-3 years as I switch companies.
A craftsman sharing blueprints for screws or instructions for wood joinery isn't putting themselves out of the business of constructing furniture.
SWE is so far down at the bottom of the hole of having the tooling we need we could do this for a few more decades and there'd still be oodles and oodles of work to do. Right now we're digging tunnels with spoons.