I don't think there's a one size fits all solution here, and there are constraints that the author isn't seeing.

In favor of a service are cases where users want plugins, and the upstream doesn't want to maintain them. An example is anything that touches DNS, like cert-manager, external-dns, things like that. There are thousands of DNS hosts, and they each have their own API. So nobody wants to provide support for all of them out of the box -- the upstream maintainer's entire life will become approving PRs for obscure DNS services. The maintainer can't test them, because they don't have an account, so can't own the quality of the final product anymore. Therefore, nobody does this. Services are an answer to this problem -- the thing you actually want to use defines an API for DNS services, and the DNS provider gives you a program that can receive messages to update DNS, and everyone is happy. You just run it as a sidecar, and you can update it when your DNS provider changes their API, and update the other thing whenever they add a new feature that you want. The coupling is loose, so you don't get the same perfect reliability as a purpose-built "update foocorp dns whenever an ingress rule adds a hostname", but it's pretty good.

(I honestly don't know if this is actually how cert-manager and external-dns work. I use cert-manager and it builds in libraries for the DNS providers I use, with the caveat that they aren't accepting any more. I don't use external-dns, but I heard some rumblings about making a standard a few years back for this sort of thing. Didn't check in on the status of either. It's just a hypothetical example ;)

Libraries are unhelpful here because there are a billion programming languages, and the upstream provider will never choose your programming language of choice as their priority. Additionally, container builds are hard and I've never heard of anyone with a reliable way of taking some sort of upstream project and building it with local add-ons at every upstream commit, tagging stable versions in parallel with the upstream, etc. Definitely possible, but out of reach of the average container operator. Things like Go without dynamic linking (a feature I agree with, BTW), and container builds make services more critical for the plugin type use case. (My dream is to just write libraries in something that compiles to WebAssembly and use that to implement a plugin system in applications that need it. Some people are kind of sort of doing this; Envoy for example.)

On the other hand, sometimes you need the deep integration that only libraries can provide. It's popular to use sidecars to add network features like distributed tracing and mTLS; linkerd and Istio are examples. But these are exactly the use cases where you should use libraries instead of services. You need to see the TLS handshake so that your application can make authorization decisions based on the peer that you're connected to. To do distributed tracing, you need to copy the X-B3-Trace-Id header out of the incoming HTTP request into the outgoing HTTP request. Libraries can do that for you, but services can't.

In summary, the answer on library or service is "it depends". Hopefully this comment adds a little more nuance than the original article.