Phil Calçado, a software engineer, writes about microservices, service mesh, Back-End for Front-End, and engineering process.
HN commenters cite his microservices history as candid, link his service mesh pattern and DigitalOcean departure posts, and discuss BFF-style specialized backends.
The article imo misuses the term BFF a bit, but perhaps its meaning has evolved over time. I was at SoundCloud when BFF was being introduced as an important piece of the microservice architecture--this post explains the purpose well[0]. BFFs can enable you to build more general-purpose and domain-specific services with few assumptions as to how they are used and their callers. BFFs then provide a composition layer you can use to, e.g., call one service to get a list of tracks, then call an authorization service w/ the list of track IDs to get geo-specific distribution rules for them, and compose that together in one materialized presentation view for the clients of the BFF.
Eventually I think there was some work to move to GraphQL, which can solve some of the same problems. But GraphQL is a technology, and BFF is more of a pattern. There is a later reflection on that blog that makes this distinction, which I only read today.[1] It makes another observation that I kind of forgot about, because it was hiding right in front of my face as a worker there:
"The defining characteristic of a BFF is that the API used by a client application is part of said application, owned by the same team that owns it, and it is not meant to be used by any other applications or clients."
The ownership model is indeed a big deal. In practice, it helped in many ways to have a sort of intermediate layer between the client applications and the rest of the architecture. For example, in the…
The author suggests a common opinion on patterns, that I have seen violated a billion times:
> Two people with a common set of patterns find it easier to communicate [...] than those without one.
> [...] writing down our shared context lowers the barrier to entry.
In my experience this is often not the case. Patterns come along with labels and the labels will be put everywhere in a codebase. Assumptions get made and replace discussions, leading to a diluted codebase. For example Repositories will become synonyms for "thing that does database access", and will then be reduced to stupid GetByID wrappers [1]. Even worse, some patterns make entry really hard.
I used to work with C# and ASP.NET MVC. There, a view is the thing that contains markup, the thing controlling the input is the controller. Then I started using Flask and was utterly confused, since there the functions with the @app.route decorators, which are run on the server and then return markup rendered via jinja2 templates, are called view functions. In Django this is understanding is the same.
I was really baffeled. I could not reapply my understanding of the patterns across these domains. This is just one explicit example that I wrote about in my blog [2], but I really made the general experience that patterns replace or inhibit discussions, rather than improving communication and understanding.
[1] http://philcalcado.com/2010/12/23/how-to-write-a-repository/
[2] http://www.cessor.de/on-patterns
Identifying changing "stuff" in the real world is for me a fundamental topic of any serious data modeling for any kind of software (be it an API, a traditional database stuff, etc). Identity is also at the center of the entity concept of Domain-Driven Design (see the seminal book of Eric Evans on that: https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215).
I started changing my way of looking at identity by reading the rationale of clojure (https://clojure.org/about/state#_working_models_and_identity) -> "Identities are mental tools we use to superimpose continuity on a world which is constantly, functionally, creating new values of itself."
The timeless book "Data and reality" is also priceless: https://www.amazon.com/Data-Reality-Perspective-Perceiving-Information/dp/1935504215.
More specifically concerning the article, I do agree with the point of view of the author distinguishing access by identifier and hierarchical compound name better represented as a search. On the id stuff, I find the amazon approach of using URN (in summary: a namespaced identifier) very appealing: http://philcalcado.com/2017/03/22/pattern_using_seudo-uris_with_microservices.html. And of course, performance matters concerning IDs and UUID: https://tomharrisonjr.com/uuid-or-guid-as-primary-keys-be-careful-7b2aa3dcb439.
Happy data modeling :)
EDIT:
- add an excerpt from the clojure rationale
Having read one of the success stories linked in the beginning (http://philcalcado.com/2015/09/08/how_we_ended_up_with_microservices.html) I think I am starting to get it. That was a rather candid article describing a team which after having got burned by a sprawling "monorail" architecture decided to split it up into services (nothing micro- there) based on organizational viewpoint (if there is some knowledge about a part of application shared by 3-4 engineers it makes sense to split it into a separate module so it can be developed faster). And as I am inferring from the pictures their services don't call each other much so it is really close to a modular monolith. So if "migrating to microservices architecture" really means "splitting that damned monorail into something more manageable" then it is a really good idea after some point.
At my company we have a bunch of content that's only archived on SoundCloud. The main barrier I've had to backing up original uploads (only available through the web interface) is the terrible reliability of all the AJAX calls. Even with browser automation, it requires a LOT of error-handling just to navigate between resources successfully.
It seems that all these microservices[1] are there for the sake of blogging about using microservices[2] as there haven't been any new significant new features delivered in years, and the whole application now seems to be delivered through AJAX calls.
[1]: https://developers.soundcloud.com/blog/building-products-at-soundcloud-part-3-microservices-in-scala-and-finagle
[2]: http://philcalcado.com/2015/09/08/how_we_ended_up_with_microservices.html
Agreed! A SPA using an RPC API usually makes the most sense. I've wasted so much time over my career trying to jam functional concepts into REST resources for little gain.
I really like the idea of each app getting it's own specialized backend. Have you heard of the BFF pattern?
https://philcalcado.com/2019/07/12/some_thoughts_graphql_bff.html