[HN Gopher] Write libraries instead of services, where possible
       ___________________________________________________________________
        
       Write libraries instead of services, where possible
        
       Author : mooreds
       Score  : 244 points
       Date   : 2023-11-23 14:21 UTC (8 hours ago)
        
 (HTM) web link (catern.com)
 (TXT) w3m dump (catern.com)
        
       | mooreds wrote:
       | I think this sentiment is a partial cause of the trend towards
       | self-hostable, downloadable software too.
       | 
       | The customer has a cost when they operate a library instead of
       | consume a service, no doubt. They also get more control (no
       | surprise upgrades, availability is their responsibility) and
       | assurances (no worries about the service suddenly being end of
       | lifed).
        
         | taneq wrote:
         | When you use a library from an outside source, if you update
         | that library, it might break your build.
         | 
         | When you use an outside service, they might break your system
         | at a time of their choosing.
        
           | mooreds wrote:
           | Exactly. It'll break sometime (it's software). So when do you
           | want it to break? And is the benefit of controlling/planning
           | the timing of that breakage worth the cost of operating the
           | software?
           | 
           | As always, it depends. Questions I'd ask:
           | 
           | * How critical is the software to your application's proper
           | functioning?
           | 
           | * How big is the team?
           | 
           | * Who are your customers and what are customer expectations
           | around your application's proper functioning?
           | 
           | * How often does the library change?
           | 
           | * What expectations does a service set around backwards
           | compatibility? What commitments are made?
        
           | nijave wrote:
           | >When you use an outside service, they might break your
           | system at a time of their choosing.
           | 
           | Well sure, but if this is important to you, you might
           | consider a contract with the company that lays out cases and
           | conditions where breakage is acceptable.
        
             | marcosdumay wrote:
             | Or you internalize the functionality with a library.
        
             | TeMPOraL wrote:
             | Yes, SLA is a way to turn literal _existence_ of a product
             | into a pay-as-you-go offer on top of a service.
        
           | JohnFen wrote:
           | Yes. And if an updated library breaks you, you can fix it
           | easily by rolling back to the earlier version of the library.
           | If an outside service breaks you, you're hosed until they fix
           | the service or you rework your code to route around the
           | breakage.
        
       | mooreds wrote:
       | Previous discussion:
       | https://news.ycombinator.com/item?id=26398960
        
         | ChrisMarshallNY wrote:
         | I thought it sounded familiar.
         | 
         | Thanks!
        
           | mooreds wrote:
           | HN doesn't repeat, but it sure does rhyme. :)
        
       | _ZeD_ wrote:
       | (so that I can use your library and not depend on your service)
        
       | cosmolev wrote:
       | It was like this 20 years ago. "software that can be run by the
       | user" - good old times.
        
       | closeparen wrote:
       | Services usually depend on databases. Libraries usually don't.
       | Either you need to support every storage backend your users might
       | have, require them to write an integration layer from your
       | generic hooks, or expect them to provision and manage new storage
       | when using your library. In any case you are asking them to do a
       | lot more work (manage the data) and in some sense breaking
       | encapsulation by making them responsible for this.
        
         | z33k wrote:
         | Great point. In my opinion it is possible and maybe even ideal
         | to do both: make it easy for anyone to run their own service
         | while also running your own service so that users have the
         | option to not have to manage the data, patching and ops side.
        
         | bee_rider wrote:
         | The underlying point of the post seems to be that it is better
         | to ask the user to do more work, than the developer.
        
         | Kinrany wrote:
         | This shows that we lack good abstractions over storage.
        
           | ben_jones wrote:
           | It's more like data storage needs are not one size fits all
           | so it's better left to the user who best knows their storage
           | needs.
        
             | miningape wrote:
             | This is interesting, makes me wonder if a "dockerised"
             | database is something people could use. I mean a database
             | frontend with its own language/protocols/whatever that
             | allows you to define the data structure but leaves the
             | specific storage engine or format as a backend detail that
             | can change from platform to platform.
        
               | mjr00 wrote:
               | > I mean a database frontend with its own
               | language/protocols/whatever that allows you to define the
               | data structure but leaves the specific storage engine or
               | format as a backend detail that can change from platform
               | to platform.
               | 
               | That's more or less a description of SQL.
        
               | rekwah wrote:
               | Postgres wire format is indirectly getting there. Plenty
               | of tools use that with wildly different storage engines
               | on the other end.
               | 
               | A clean room implementation would likely yield different
               | results but there appears to be some appetite for a
               | solution.
        
             | crabbone wrote:
             | Nah. It's not that. We lack a concept that can organize
             | storage. Let me illustrate this.
             | 
             | So, until some years ago there was complete nonsense and
             | anarchy in Linux networking management. That is until we
             | got the "ip" program. There's still nonsense and anarchy,
             | because the "ip" program doesn't cover everything, but it's
             | on the right track to organize everything Linux knows about
             | networking under one roof. So, vendors today, like, say,
             | Melanox (i.e. NVidia) choose to interface with "ip" and
             | work with that stack rather than invent their own
             | interfaces.
             | 
             | When it's extendable in predictable and convenient ways,
             | user will extend and enrich functionality.
             | 
             | Now, compare this to Linux storage... I want to scream and
             | kill somebody every time I have to deal with any aspect of
             | it because of how poorly mismanaged it is. There's no
             | uniformity, plenty of standards where at most one is
             | necessary, duplication upon duplication, layers... well,
             | forget layers. Like, say, you wanted a RAID0, well, you
             | have MD RAIDs, you have LVM RAIDs, you have ZFS RAIDs, you
             | have multipassing with DM (is that a RAID, well sorta'
             | depends on what you expected...) also, well, Ceph RDB are
             | also kind of like RAIDs, DRBD can also sort of be like a
             | RAID...
             | 
             | Do you maybe also want snapshots? How about encryption? --
             | Every solution will end up so particularly tailored to the
             | needs of your organization that even an experienced admin
             | in this very area your org is specializing will have no
             | clue what's going on with your storage.
             | 
             | Needs can be studied, understood, catalogued, rolled into
             | some sort of a hierarchy or some other structure amenable
             | to management. We haven't solved this problem. But we have
             | an even bigger one: no coordination and no desire to
             | coordinate even within Linux core components, forget third-
             | party vendors.
        
           | yjftsjthsd-h wrote:
           | The space is complex enough that I wonder if it's _possible_
           | to make abstractions that aren 't horribly leaky.
        
             | pphysch wrote:
             | I blame the SQL "standard". It's a massive, unnecessary
             | abstraction layer that only complicates attempts to build
             | bridges between code and relational databases (which I
             | believe is the most general-purpose paradigm).
             | 
             | Personally, I am working on a modern Python ORM for
             | PostgreSQL and PostgreSQL alone.
        
           | osigurdson wrote:
           | You cannot abstract away a 3 order of magnitude difference in
           | bandwidth and latency.
        
             | pclmulqdq wrote:
             | Where did you get a 3 order of magnitude difference? Are
             | you still using hard drives for your storage medium?
        
           | jandrese wrote:
           | Isn't this what SQL is supposed to be? You bring the DBI for
           | your database and plug it into the app. Shame that it doesn't
           | work out so well in practice.
        
           | Too wrote:
           | Cloud providers are (counter to intuition about their lock-in
           | incentives) improving the space of this. Lots of tools now
           | allow configuring storage by just pointing to various cloud
           | stores, most often a S3 compatible api, not exclusively
           | though.
           | 
           | K8s PersistentVolume is another decent shot at storage
           | abstraction, only a bit raw.
           | 
           | Finally, more and more tools expect you to have a Postgres
           | they can plug into as backend.
           | 
           | All above assumes you want to treat the library data as a big
           | unknown blob. Once data start being corrupted and need
           | bespoke repair, things are less fun. Access and retention is
           | another fun rabbit hole.
           | 
           | Data is complicated.
        
         | jbverschoor wrote:
         | sqlite is a library
         | 
         | zeromq is a library
         | 
         | That's all the storage you need
        
           | bilalq wrote:
           | No? If you have a horizontally scaled architecture or
           | anything with multiple nodes, you can't just get away with
           | "sqlite is a library".
        
             | TeMPOraL wrote:
             | SQLite is more about letting you get away with _not having
             | a horizontally scaled architecture or anything with
             | multiple nodes_ in the first place.
        
         | ImPleadThe5th wrote:
         | I'm maybe naive, but is it not possible to supply a repository
         | interface for the user to implement? Bring your own glue?
         | 
         | The library uses only the interface to work with whatever
         | orm/db connector exists in the client project.
         | 
         | If services at any given company all use a standard db library,
         | it could even directly interface assuming your using that. I
         | don't think we're talking about public apis and packages here.
        
         | __MatrixMan__ wrote:
         | It's only an unreasonable amount of work if you assume that the
         | user is managing a separate storage backend for each library.
         | If you take the Tim Berners-Lee approach (re:
         | https://solidproject.org/) then each user is only managing one
         | storage backend: the one that stores their data. The marginal
         | cost of hooking in one more library to the existing backend is
         | low.
         | 
         | We just have to get a little more fed up with all of these
         | services and then the initial cost of setting it up in the
         | first place will be worth it. Any day now...
        
           | closeparen wrote:
           | I think most interesting web services are providing
           | structured access to the same data for multiple people. A
           | private, individual data silo wouldn't get the job done
           | unless combined with some kind of message-passing. A silo to
           | which users can invite peers is interesting, but it's an
           | important characteristic of many web services that the
           | specific read and write transactions allowed are application-
           | defined... you don't actually want to give your collaborators
           | general read or write access at the storage level.
           | 
           | For example, it's important that I can add this comment, and
           | I can't delete your comment, but the moderators can. The
           | "storage" software would have to know something about the
           | business logic of a web forum to make that happen.
        
             | __MatrixMan__ wrote:
             | I think we just need smarter browsers which can be
             | configured to know who we trust in which dimension.
             | 
             | If I want to leave a comment on an article and then delete
             | it, I can publish the comment in my pod, and I can also
             | publish the deletion. If you've got your browser in a mode
             | where it's interested in my comments, it can pull in the
             | data from my pod and render it in context with the article
             | --whether or not the article's author cared to provide a
             | comments section.
             | 
             | If you drop the idea that anyone is authoritative about how
             | it all comes together on the viewer's screen, you can also
             | dispense with the headaches of being that authority (e.g.
             | services).
        
         | crabbone wrote:
         | The title of the article literally says "where possible". You
         | found a case when it's not possible, and decided to argue
         | against that...
         | 
         | No, not all services come connected with a database.
         | Alternatively, often times a database is an artifact of tenancy
         | and the need to manage users which would not be needed, had the
         | functionality be exposed as a library.
         | 
         | More importantly, whether users realize this or not, a library
         | is more beneficial for them than a service in majority of
         | cases. Much in the same way how it's almost always better to
         | own something than to rent it.
         | 
         | Just to give some examples of the above: all the Internet of
         | crap stuff, all sorts of "smart" home nonsense which requires
         | that you subscribe to a service, install an app on your phone
         | and send all your private data unsupervised to some shady Joe
         | Shmo who you know nothing about. To be more specific, take
         | something like Google Nest thermostat. There's no reason this
         | contraption should ever go on the Internet, nor should it
         | require to know your street address, nor your email etc. In
         | fact, the utility it brings is very marginal (saves you few
         | steps you'd have to make to reach for the boiler's controls to
         | program it). It absolutely could've been designed in such a way
         | that it doesn't connect to the Internet, or, at least, to never
         | leave the local area network, and yet it's a cloud service...
        
       | hbn wrote:
       | Is this really a common scenario where there's a choice between
       | these 2 options that isn't obvious? I've never considered
       | libraries and services to be two equal options of distributing
       | functionality, and you just pick one of them. It's usually a
       | function of practicality and monetization.
        
         | marcosdumay wrote:
         | > Is this really a common scenario where there's a choice
         | between these 2 options that isn't obvious?
         | 
         | In my experience, no, it isn't any common. But it is somewhat
         | common for people to ignore the obvious option and go for
         | services anyway.
        
         | crazygringo wrote:
         | Exactly. I've never run into a situation where there was even a
         | choice.
         | 
         | Is it something that relies on a private database, queue,
         | massive processing, dedicated hardware, shared state, something
         | geographically distributed? It's a service out of necessity.
         | 
         | Or is it just a bundle of quickly executing code? Then it's
         | obviously a library.
         | 
         | I've never seen anybody try to turn leftPad() into a service.
        
           | sokoloff wrote:
           | Fair to assume it's a joke, but: http://left-pad.io/
        
         | citrin_ru wrote:
         | In my experience a new micro-service considered the default
         | option for anything which could be done as a micro-service
         | nowadays. Library API design is the lost art (almost). And the
         | choose is not always obvious for non-technical reasons.
         | Consider a following example: you have 3 micro-services X, Y, Z
         | which need to interact with a platform G but this interaction
         | requires non-trivial chunk of code. It can be done as a library
         | or as a new adapter micro-service A which will encapsulate
         | knowledge about platform G and will interact with X, Y, Z the
         | way it would be easier for X, Y, Z developers to integrate.
         | Micro-service will add network latency but will allow to
         | make/deploy all changes only to service A. With a library one
         | would have to test and release a new version and then ask X, Y,
         | Z maintainers to switch to this new version. In some
         | organizations it will be a very slow process because X, Y, Z
         | can put an update request (from the library team) at the bottom
         | of the backlog. With a micro-service A teams X, Y, Z would have
         | much less power to stop/slow development.
        
           | geraldwhen wrote:
           | This is making technology objectively worse to solve people
           | problems, and this only expands.
           | 
           | More software needs iron clad leadership and control. Any
           | organization that lacks this can't help but produce shit
           | software. There has to be a single person with real decision
           | making power than can force upgrades and prioritization of
           | work, and they need to be able to axe people or teams who
           | can't hack it.
        
             | fmbb wrote:
             | OK but most business compete in a market. And the people
             | they employ are in a labour market.
             | 
             | It seems that worse is better.
             | 
             | What we see is just another manifestation of the current
             | economic paradigm. Waste is winning.
             | 
             | Making too many pairs of jeans so we burn tons of perfectly
             | good new pairs daily wins.
             | 
             | Throwing hundreds of engineers on problems bashing out
             | hundreds of thousands of lines of code sending megabyte
             | messages between dozens of service instances in multiple
             | kubernetes clusters appear to be a winning move. Otherwise
             | someone would beat them, right?
        
               | geraldwhen wrote:
               | Most engineering orgs don't understand or feel "the
               | market" until mass layoffs. They exit their companies
               | with beautiful resumes touting micro services and k8s.
        
           | bardsore wrote:
           | Worked a place where we switched from having a client library
           | to making the other teams use our APIs directly themselves.
           | Of course, we had to do the switch for them because they were
           | too busy... Pretty much just copy-pasted the library code
           | directly into their projects.
        
         | mjr00 wrote:
         | If you're distributing something publicly, it's fairly obvious
         | which to pick, yeah.
         | 
         | It's less obvious for internal systems and architecture. For
         | example, your company wants to add domain-specific auditing to
         | all of your existing services. You could have every service add
         | a library dependency that lets them just call
         | `auditor.log(...)` and the library internally writes to
         | storage. Or you could add an auditing service with a full
         | HTTP/GRPC API. Or you could go halfway and build an auditing
         | service but provide a library that acts as an interface.
         | 
         | There's no right answer for this IMO, all those approaches have
         | pros and cons.
        
         | bilalq wrote:
         | This was a really common dilemma at Amazon. The prevailing
         | wisdom was opposite to the advice in the article though. Unless
         | you had an exceptional reason, your functionality and data
         | should be exposed as service, not a library.
        
         | manicennui wrote:
         | Based on the fact that everyone seems to turn every desktop app
         | into a service, yes?
        
         | crabbone wrote:
         | Oh, absolutely. Service brings convenience to the backoffice
         | and money! Libraries suck to support and hard to sell.
         | 
         | Of course users want libraries but vendors want services. There
         | are plenty of examples where something could've been a library,
         | if the vendor had user's interest at heart, but instead it's
         | sold (or rather rented out) as a service.
         | 
         | Go to Amazon marketplace, for example. Virtually everything
         | there is a product that should've been a library but is sold as
         | a service...
        
       | sameg14 wrote:
       | Yeah but then who is responsible for maintaining the library? If
       | you have a bunch of internal teams that depend on your library
       | and there is an issue or a feature request, you're back to the
       | same position of being the one that does the work to implement.
       | Better to have a service IMO, you can get telemetry out of it and
       | scale it out or replace internals without having to worry about
       | who will get affected.
        
         | sidlls wrote:
         | Many engineering organizations have "platform teams"--teams
         | that have as their sole responsibility maintaining shared
         | libraries and "core" services for the entire platform.
        
         | marcosdumay wrote:
         | As opposed to being responsible for maintaining and doing
         | operational support of the service...
         | 
         | I still don't get what advantage exactly you are expecting.
         | 
         | Scaling it is only ever a problem for the service; you don't
         | even have to think about it in a library. You can get telemetry
         | from a library just as well as from a service; your users may
         | find that a bit invasive, but it's still way less invasive than
         | calling your service. And you can replace the internals of
         | whatever, without having to worry about who will get affected,
         | that's what defines internals.
        
         | hamandcheese wrote:
         | If you can maintain a stable service API, why can't you
         | maintain a stable library API?
         | 
         | I don't see any inherent reason why it should be easier to
         | change the behavior of a service rather than a library.
        
           | TeMPOraL wrote:
           | Because if you ship code to users (library), you lose
           | control. You may want to change something, but your users
           | will just tell you to go pound sand. Conversely, if you keep
           | the implementation on your side (service), you get to control
           | how things work and when things change, and your users don't
           | have a say in this.
           | 
           | It's an ownership and control issue.
        
             | bigstrat2003 wrote:
             | I don't see the issue here. If I release my_fancy_lib
             | 2.0.0, and I have users who only ever want to stay on the
             | last 1.x release, that's fine. It's no skin off my nose if
             | users choose to stay on an old version forever.
        
               | TeMPOraL wrote:
               | Yeah, exactly. However, if you were to make it a service,
               | those users would _have to_ switch to 2.0.0 or stop using
               | it, as 1.x no longer exists.
        
       | taneq wrote:
       | Write libraries instead of services. Where necessary, wrap
       | libraries in services.
        
       | buzzy_hacker wrote:
       | Related: Who Does That Server Really Serve?
       | 
       | https://www.gnu.org/philosophy/who-does-that-server-really-s...
        
         | psd1 wrote:
         | Stallman performs the vital function of pinning the Overton
         | Window to the left, which benefits those of us with more
         | nuanced views.
         | 
         | I'm not going to run my own mail server in 2023, etc.
        
           | teddyh wrote:
           | > _I 'm not going to run my own mail server in 2023, etc._
           | 
           | But many do. It's still not that hard.
        
       | slifin wrote:
       | I hope GraalVM's Polygot runtime will eventually allow more
       | companies to go with libraries over services in more situations
       | for multi-language businesses.
       | 
       | And Polylith for better reuse across projects generally.
        
         | pas wrote:
         | > Polylith
         | 
         | this sounds very nice on paper (it sounds common sense trivial
         | utopia that everyone sets out to do anyway, but somehow life,
         | entropy and deadlines get in the way), but ... is there a
         | bigger real life project using something like this?
        
         | cornfeedhobo wrote:
         | I wish I could nuke GraalVM from the earth. It ruined my life
         | for 2 years and I will never forgive it. It's a very stupid
         | idea, pushed by CTOs that think Java's "write once, run
         | everywhere" is still relevant. It literally runs every language
         | slower and introduces all kinds of build pains.
         | 
         | Ugh, I can't believe I had to read your comment this morning.
         | smh
        
           | eurekin wrote:
           | I was stumped the first time I read about Graal. It felt like
           | 15 years too late and made zero sense to me.
           | 
           | Please, if you could share more about that, I'd be happy to
           | share the pain
        
       | NBJack wrote:
       | It's all fun and games until you hit version n+1 or n+2, and
       | often realize how slow many customers are to upgrade the library.
       | Then there are the potential conflicts in your own dependencies.
       | And let's not forget the occasional breaking change you
       | introduced.
       | 
       | You are now sacrificing the money saved by not hosting to
       | maintain what will likely be a growing matrix of possible
       | versions, underlying assumptions, and my personal favorite: weird
       | customer deployment scenarios that break your library
       | functionality. Bonus points if you are developing in a language
       | without strong typing, or need to integrate with a dependency
       | manager.
       | 
       | Plus, if there was anything about your service that leveraged
       | unique algorithmic improvements or some other proprietary tech,
       | it is now at the mercy of anyone with a decompiler and sufficient
       | time.
       | 
       | I suspect the author may change their mind if exposed to scaled
       | up solutions and technologies.
        
         | mooreds wrote:
         | I thought the author addressed that point:
         | 
         | "But this assumes that slow-to-upgrade users can have negative
         | effects on everyone else. If one user can't have a negative
         | impact on other users, then you don't care if some users are
         | slow to upgrade; they're only hurting themselves."
         | 
         | There's still the support issue, I agree. If a customer paid
         | you money and they are on version n-10, they still expect
         | support.
         | 
         | > Plus, if there was anything about your service that leveraged
         | unique algorithmic improvements or some other proprietary tech,
         | it is now at the mercy of anyone with a decompiler and
         | sufficient time.
         | 
         | This is a valid point. My answer would be: it's all tradeoffs,
         | but if your secret sauce is so valuable that it would be worth
         | decompiling and can't be protected with decent pricing, license
         | terms and lawyers, run a service.
         | 
         | There are plenty of technologies that are not worth decompiling
         | for your average business customers.
        
           | jampekka wrote:
           | In my experience the more they try to hide the sauce the
           | worse it is.
           | 
           | Quite logical though if the secret is that your secret sauce
           | is bland and off-flavor copy of a canned soup. Which it
           | usually is.
        
           | LtWorf wrote:
           | If your updates don't break every single time, your customers
           | will be more likely to do them.
        
         | gjadi wrote:
         | > It's all fun and games until you hit version n+1 or n+2, and
         | often realize how slow many customers are to upgrade the
         | library.
         | 
         | How is that different with services? I don't develop services,
         | but I can imagine that before breaking the services, you have
         | to poll with your biggest customers and you don't break until
         | they are ready to move to the new version. The alternative I
         | can imagine is to keep providing the old services with a grace
         | period (e.g. /v1 will be available until dec next year).
         | 
         | What am I missing?
        
           | sokoloff wrote:
           | Many changes are believed to be non-breaking and so you can
           | be running only one version in prod. (Most of the changes
           | _believed to be_ non-breaking are non-breaking.)
           | 
           | With a library, you end up with many different minor or point
           | versions running without control over it.
        
             | gjadi wrote:
             | Ok so the benefits here are transparent upgrade. Thanks.
        
             | genman wrote:
             | Emphasis on "are believed". This actually puts clients into
             | risk of having breaking changes out of their control.
        
           | materielle wrote:
           | The idea is to link a thin client library into the user's
           | code.
           | 
           | Then the thick client is controlled server side by the devs.
           | 
           | If you design the thin and thick client intelligently, you
           | can make a lot of changes to the system by merely modifying
           | the thick client (which you control), without needing to
           | update the thin client.
           | 
           | Problems tends to come in a few flavors, namely that this
           | increases complexity and that _some_ changes will always
           | require modifying the thin client.
           | 
           | The biggest pitfall, though, is that you have to actually put
           | thought into the thin client design. "Thin" is an emergent
           | property of a well thought out client. You can't just "touch
           | thin_client.java" and think because you named it "thin" that
           | it's inherently decoupled from the service. You have to
           | actually put thought into it.
           | 
           | Your example is exactly right. The service can support either
           | v1 or v2 depending on the version of the thin client.
           | 
           | The main other technique is to have the thin client
           | communicate in a relatively abstract and generic manner. For
           | instead a "write()" endpoint that accepts an "options"
           | dictionary.
           | 
           | "write()" is so generic that it probably won't have to
           | change, and changes in behavior can be modified by shoving
           | stuff into dict, perhaps with a "version" field to instruct
           | the server how to interpret the call.
           | 
           | When you add a new feature, you can bump the thin client to
           | v2 and shove new options in the dict. Then the server can
           | support v1 and v2. But also, you can modify the server to
           | handle v1 differently. E.g the absence of a
           | "disable_new_feature" key automatically opts v1 callers into
           | the new feature.
           | 
           | I think the details are are really coupled into what you are
           | engineering and what you want to roll out. There's no magic
           | bullet, and this increases the complexity of your code. Good
           | engineering in my opinion is deciding when these approaches
           | are worth it and _how_ they should be implemented.
        
             | gjadi wrote:
             | I don't quite understand what you are saying.
             | 
             | As per the article, the advantage of a library over a
             | service is that you don't have the burden of maintaining
             | the said service. How having a thin client and a server
             | helps?
             | 
             | I also don't see how "shoving new options in the dict" can
             | help. From my POV, if the client needs to be updated to
             | benefit from the new features, then there is no way around
             | it, work has to be done. From there, I much prefer having
             | sensible name, parameters, etc. from a library that can be
             | leveraged by static typing rather than a documentation for
             | a JSON API (I know API-as-specs exist but I've never used,
             | maybe that's why I think that).
        
           | zja wrote:
           | You have the same problem with services and libraries when
           | you're introducing a breaking change. With services you can
           | make non-breaking changes like security patches on the server
           | side, without needing to coordinate with a customer.
        
             | LtWorf wrote:
             | And with libraries you can't make breaking changes?
             | 
             | The fact that I don't need to recompile everything whenever
             | libcurl or libssl has a security fix proves otherwise.
        
           | grogenaut wrote:
           | Simple answer is YOU control the deploy of a server in
           | miroservices, so YOU decide when it goes live. You aren't
           | playing spreadsheet telephone at scale to get everyone even
           | im an internal org to update. If you're smart you have your
           | callers send version information and you usually just add
           | fields, only removals or renames cause version issues. If
           | you're having everyone use a library they control when they
           | update the logic and you have less telemetry when some wierd
           | corner of your company is using out of date logic.
        
         | noah91734 wrote:
         | > It's all fun and games until you hit version n+1 or n+2, and
         | often realize how slow many customers are to upgrade the
         | library.
         | 
         | Given how frequently needless breaking changes are made, or
         | features are removed and paywalled, I would consider this a
         | feature rather than a bug. Sometimes I have higher priorities
         | than working to support someone else's breaking changes.
         | 
         | Two years ago, I was using an official library for interfacing
         | with a video chat service, and they decided to break the
         | underlying API without updating their library, so I had to
         | rewrite the library myself.
        
         | kuchenbecker wrote:
         | Write a library, deploy it as a service if necessary.
        
         | crabbone wrote:
         | This is a completely broken model.
         | 
         | You are wrong by pushing your changes on "slow to update"
         | customers. Customers know when to update much better than you
         | do. If you are trying to update before they want to, you are
         | doing them a disservice.
         | 
         | This attitude is inspired by the desire to sell more, and often
         | times, it means to sell more unwanted crap, where customers are
         | trapped by the "package deal", where they are either forced to
         | update to gain useless features and the headache resulted from
         | various inconsistencies and defects coming from the last
         | update, or they are unable to get the product at all (because
         | the provider cancels support or wouldn't sell older versions
         | etc.)
         | 
         | In other words, you with straight face describe some really
         | shady practice and you don't even realize how bad it sounds.
        
           | actionfromafar wrote:
           | It can be that, but it doesn't have to be. It depends on the
           | business model and it's quite orthogonal to library vs
           | service.
        
         | fsloth wrote:
         | Yes you need to have n versions you support in parallel in the
         | wild. One per released incompatible binary API (so in semver
         | 1.x, 2.x etc). We support about 30 libraries with 5 ppl spread
         | around a fortune 1000 org here and there. It's quite tenable,
         | we are just super strict regarding ticket policy and release
         | notes, so we always know what's released where. Just have a
         | system. Stick to it. Keep things organized. Works like a charm.
         | If someone wants a service out of those someone just packages
         | them to docker and puts them to backemd somewhere. We can focus
         | on pure business logic, someone else maintains services etc.
         | Really nice setup.
        
       | wqtz wrote:
       | I don't get it. Can anyone kindly share where this practice can
       | be applied to a commercial software? I am struggling to wrap my
       | head around "how run by user" works where they are using a
       | commercial software service.
        
         | Sanzig wrote:
         | License fees, just like the old days. Either fixed cost to
         | license the library, a royalty based scheme (# of
         | users/installs), or both.
        
         | denton-scratch wrote:
         | There's some confusion in this thread between "service" as out-
         | of-process functionality called via IPC or over the network,
         | and "service" as something done by a service-provider for
         | money, such as emptying your bins.
        
         | catern wrote:
         | Ultimately, it can't. Proprietary software has fundamental
         | limitations that force proprietary software developers to
         | choose technically inferior designs. It's why in the long run
         | proprietary software is doomed.
        
       | throwaw12 wrote:
       | "where possible" is a keyword here and easy to argue about. For
       | example:                  * my logic requires a database        *
       | my logic should be isolated for compliance reasons        * my
       | logic accesses a service which is not available for everyone
       | * my logic should be processed async and needs to store state,
       | how do I make sure library owners have that environment        *
       | customers embedding my library are not upgrading it frequently,
       | which leaves us to support 15 years of libraries        * ...
        
         | leethomas wrote:
         | Hm, it feels like all of these except for number 2 and the last
         | one can be solved by appropriate interfaces and documentation.
        
           | mooreds wrote:
           | On that topic, I love this article from Stripe (in 2017)
           | about how they version their APIs:
           | https://stripe.com/blog/api-versioning
        
           | throwaw12 wrote:
           | how about 1?
           | 
           | Imagine a scenario, your service is a low traffic, but
           | service which embeds you as a library is a high traffic with
           | many instances and always opens DB connection.
           | 
           | Why should you optimize your Database for high traffic use
           | case, when your use case is really a low traffic?
           | 
           | And then repeat this for 10 other libraries and library
           | owners. Everyone is optimizing for nothing.
           | 
           | make it even more difficult, 100 different types of services
           | with different traffic patterns are embedding your library
           | with different behaviours when it comes to managing DB
           | connection state
        
           | throwaw12 wrote:
           | how about 3?
           | 
           | Scenario: your service is accessing a service which exposes
           | PII data and you only process them.
           | 
           | Service which embeds your service enabled audit logs of
           | network requests and made it visible to everyone in the
           | company. You have created a risk unintentionally
        
       | whalesalad wrote:
       | It's hard when you have N services that need a lockstep migration
       | from v1 to v2 of the library. I tend to agree with much of this
       | but it's not a one size fits all thing.
        
       | jampekka wrote:
       | And write unix-style cli tools that can be piped to and from.
       | Make them eat and spit something structured like JSON.
        
         | JoshTriplett wrote:
         | Not as a primary interface. By all means provide a wrapper
         | around the library that does that, for users to use on the
         | command line, but there should be an underlying library for
         | other programs to use.
        
         | jjtheblunt wrote:
         | Isn't powershell a generalized version of that idea?
        
           | jampekka wrote:
           | It's a specialized version of that idea.
           | 
           | Problem with libraries are that they tie the user to a
           | specific language/OS. A cli tool eating and spitting
           | ASCII/UTF-8 is about as cross platform as it gets.
        
           | throw555chip wrote:
           | No actually, it tries to be a kitchen sink and is the
           | opposite of the UNIX concept of pipelines with small purpose
           | built utilities.
        
       | romankolpak wrote:
       | i get the benefit of offloading the admin costs onto your
       | consumers, but, as always, the devil is in the details. i've met
       | both cases where a library should've been a service, and vice
       | versa. this advice is way too broad and abstract to be practical
        
       | revskill wrote:
       | Why not both ?
        
       | 3cats-in-a-coat wrote:
       | Those aren't "either or" things. Usually services are exposed
       | through libraries. And a library requires a service if it has a
       | canonical or centralized storage or processing, which can't be
       | done locally.
       | 
       | Now, sure, we do stupid things as services, for sure. But people
       | often do it to monetize the service, or control the users. And so
       | that'll never change.
       | 
       | I recall someone making an "async HTML5 AJAX blink service" as a
       | joke for this trend.
        
       | osigurdson wrote:
       | If this isn't obvious, we are lost. Creating a rest endpoint
       | where a library would do is pure insanity.
        
         | Micoloth wrote:
         | And yet..
         | 
         | I wholeheartedly agree with your sentiment.
         | 
         | Unfortunately, the obvious economic incentive to effectively
         | paywalling code through the Internet, is so strong that _on
         | this very website_ (that was supposed to have hacker mentality)
         | most of the comments are in favour of it, because "you have to
         | make a living"...
         | 
         | Yes, I think we are lost.
        
           | fragmede wrote:
           | If you have any feasible ideas that could plausibly work
           | where people don't "have to make a living" so that we can
           | find ourselves and not be lost, we're all ears. Until then
           | we're stuck in a place where people need money to pay for
           | frivolous things like "food" or "rent" or "transportation".
           | Still, in the face of that, there's a site called GitHub
           | where people do freely share code, despite the economic
           | misincentives, so I think the kids will be alright.
        
       | NohatCoder wrote:
       | Of course the prevalent reason to make a service is that it can
       | be monetized to Hell and back again. Does it fit the customer's
       | needs? Who cares, as long as they have no clue what they will end
       | up paying until it is too late to migrate away.
        
         | AgentOrange1234 wrote:
         | Meh. Yes that happens and yes it can be frustrating. But...
         | 
         | If users want something with long-lasting support and
         | enhancements, that's going to take work. The people who do this
         | work are going to need to earn a living.
         | 
         | There are lots of ways to accomplish this. Advertising,
         | altruism, one time purchases. But charging for a service can be
         | a perfectly reasonable way of making it sustainable.
        
       | lovasoa wrote:
       | I agree with the reasoning. However, an important point to note
       | is that libraries are much harder to monetize than services.
        
       | jagged-chisel wrote:
       | You write a library, then wrap a thin service interface around
       | it. Distribute the lib as needed. Publish the service as needed.
       | 
       | Maintain the library, modifying the service on as it is affected.
       | 
       | So this effectively comes down to "write a library" as tfa
       | suggests. But there's no reason the library can't then be the
       | core of a service.
        
         | soulofmischief wrote:
         | I take "where possible" to mean that what you describe should
         | be considered an exception instead of a rule, which I agree
         | with. I do have some thin services which are libraries, but
         | above and beyond directly importing libraries is preferred.
         | With edge functions becoming more popular, this also seems to
         | be the preferred pattern, having "fat" edge functions with
         | shared code, vs many small edge functions calling each other.
        
         | mooreds wrote:
         | > You write a library, then wrap a thin service interface
         | around it. Distribute the lib as needed. Publish the service as
         | needed.
         | 
         | At $CURJOB, we did this but at a higher level of abstraction
         | (an authentication architectural component, rather than a
         | library). I think this is what the author means when they say
         | "writing a standalone server reached through a network
         | protocol".
         | 
         | We see a lot of folks who like the flexibility of consuming
         | functionality as a service or library, as they see fit. We've
         | even had customers who said "we chose you because now we want
         | you as a service, but later will want you as library" or vice
         | versa.
         | 
         | Flexibility isn't free, though. Versioning, support, backwards
         | compatibility (features and performance), even offering the
         | service all become more complex.
        
       | inetknght wrote:
       | I've been writing services... as libraries first. Then just wrap
       | the library in a very simple `main()`:
       | 
       | ``` #include "servicelib.hpp" int main(int argc, char argv) {
       | return servicelib{argc, argv}.run(); } ```
       | 
       | The library can be re-used in other apps or services.
       | 
       | Then the whole damn library is unit-testable with any arguments
       | you throw at it. Got an OS where argv may be null? You can unit
       | test that. Got a user who decided to use --iamstupid instead of
       | --iamawesome? You can unit test that too. Want to set up
       | environment variables? Well that's not thread safe, but your test
       | harness can do it before it instantiates the library object.
       | 
       | Want to use semver? You can. I use git commit checksums for
       | versions and automatic tagging to semver. It's more annoying but
       | superawesome.
        
         | agomez314 wrote:
         | Can you give details on how you do "automatic tagging"?
        
         | jampekka wrote:
         | Hundred times this. Nice to hear an odd sound of sanity amisdt
         | the architecture astronaut crowd. YAGNI.
        
         | Joel_Mckay wrote:
         | We usually wrap a set of valgrind debugged small test/demo
         | programs that hammer a library to monitor for leaks etc.
         | 
         | However, ensuring thread safety can sometimes be a challenge.
         | =)
        
         | giancarlostoro wrote:
         | Used to do this in .NET for personal projects then got pulled
         | into various dotnet projects that had their own approaches. But
         | it was really nice. What I had hoped to eventually achieve is
         | being able to hotswap the library somehow so I can have a
         | server with zero downtime for updates, but never found the time
         | to do so. I would assume I would do it via a microservice type
         | of architecture instead.
        
           | capableweb wrote:
           | You can just do this with nginx or whatever you have in front
           | (IIS if you're into Microsoft stuff I guess?). Run service at
           | port xxx1, this is your "live" port. When you wanna upgrade,
           | launch service to port xxx2, do graceful reload of config,
           | swap the ports around so "live" port now points to right
           | service, graceful reload of config again and done!
        
             | giancarlostoro wrote:
             | I should have added I was not doing a web service.
        
             | swagmoney1606 wrote:
             | IIS makes me want to explode and then die
        
           | neonsunset wrote:
           | In .NET for plugin management there are unloadable assemblies
           | so you can dynamically load and unload e.g. plugins at
           | runtime. However, it requires care, has caveats and the
           | industry generally gravitates to other techniques for zero-
           | downtime and/or rolling deployments where the replicas
           | (nodes) are at first drained, then shut down, and replaced
           | one by one or in groups but never in a way where there are
           | none to serve the requests.
        
       | flatline wrote:
       | Containers can run services without most of the overhead they
       | talk about. And as everyone else is mentioning here, a service-
       | oriented architecture is not dependent on any one tech stack,
       | it's just a way of designing applications.
        
       | prpl wrote:
       | I think this is roughly true, but at a BigCo it's not really
       | feasible/easy unless you have a monorepo or otherwise extremely
       | good build/integration tooling to deal with many repos (though Go
       | can sort of deal with this)
       | 
       | The issue is coordinating changes (and, god help you, library
       | releases) across repos is often an utter nightmare with multiple
       | PR/merge builds
        
         | scubbo wrote:
         | > it's not really feasible/easy unless you have a monorepo or
         | otherwise extremely good build/integration tooling to deal with
         | many repos[...] The issue is coordinating changes [...] across
         | repos is often an utter nightmare with multiple PR/merge builds
         | 
         | I'm coming up on a year out of $BIG_TECH_JOB (where the idea of
         | a monorepo was horrifying) and transferred to
         | $WAY_SMALLER_NON_TECH_COMPANY_WHO_USES_TECH_JOB (where the
         | enthusiastically use a monorepo), and have been really confused
         | by repeated claims like this. I really feel like I'm missing
         | something here, because lots of obviously-smart-and-experienced
         | folks repeat it. I'd really appreciate it if you could check my
         | understanding and see what I'm missing.
         | 
         | (To be clear, here I'm assuming that a monorepo is a single
         | repository which contains conceptually-distinct-but-related
         | projects - things which _could_ justifiably be their own repos,
         | but which are kept in one repo for reasons of maintenance and
         | managements - and wherein the build system is such that every
         | sub-project within the repo uses the same package dependency
         | tree, i.e. if ProjectA and ProjectB in the monorepo depend on
         | LibraryZ, then the versions of Z that A and B depend on must be
         | identical for any given commit/build. If I've misunderstood
         | that - if that's just straight-up not what a monorepo is, or if
         | it _is_ but with some extra nuance or sauce - then I guess we
         | can short-circuit the response pretty quickly :P )
         | 
         | Here's how a release of a breaking change of a library would
         | work in a polyrepo world:
         | 
         | * I publish v2.0.0 of my library
         | 
         | * Consumers of that library are notified that a new version
         | exists (via automated email notification, Dependabot, whatever)
         | \ * Anyone who _wants_ to update can do so (independently and
         | at their own rate) - anyone who's comfortable staying on the
         | old version can do so
         | 
         | ** If we really want to make things easy for consumers, we can
         | make automated PRs against their repos (this would be the
         | "extremely good build/integration tooling to deal with many
         | repos" you refer to, I suspect? Something like Spotify's
         | FleetShift[0]) to make the change - though in practice this is
         | probably way more trouble than its worth, I've only seen it
         | done for serious security vulnerabilities where a) everyone in
         | the whole damn company has to b) upgrade RIGHT THE FUCK NOW.
         | 
         | * Time goes by
         | 
         | * v1.x gets deprecated
         | 
         | * Anyone still using v1.x gets notified that they are using a
         | deprecated version and strongly encouraged to update
         | 
         | * A little more time goes by (not much!)
         | 
         | * Consequences Occur for people still using the old version -
         | this could be a visit from your friendly InfoSec enforcer, or
         | automatically failing builds, or the removal of v1.x from the
         | package repository (which will indirectly cause failing
         | builds), or...
         | 
         | Conversely, with a monorepo, the situation seems to be:
         | 
         | * I publish v2.0.0 of my library
         | 
         | * Every single team whose code is in the monorepo must
         | coordinate to make the changes to consume version 2. This
         | change, by definition, proceeds at the pace of the slowest team
         | - if one of them is underwater on oncall, or has their only
         | competent engineer on PTO, or has some quirk of implementation
         | (or dependency on old feature) which means they can't update
         | for two months, then _the whole dang monorepo_ is staying on
         | version 1 for two months; no ifs, ands, or buts
         | 
         | ** But, yes, if you want to a wide-ranging refactoring to
         | change all the in-monorepo consumers to use the new method,
         | then yeah, modern IDEs are going to have _some_ functionality
         | built-in for that within a single repo. But - by virtue of
         | being a breaking change, it's pretty likely that the change-at-
         | call-site is going to be more complex than simply changing the
         | type or name of the method being called. Maybe the returned
         | object needs different methods called on it. Maybe the method
         | requires an extra parameter (which refactoring IDEs can add to
         | the actual callsite, but cannot implement for you _fetching and
         | providing_ that parameter). At this point, either humans are
         | going to have to comb through the changes to finalize them (at
         | which point, you lose the claimed advantages of being in a
         | monorepo where changes can be done by tooling), or you're going
         | to have to implement some sort of code-parsing system to make
         | correct changes throughout (which, again, is approximately
         | equivalent to the automation work required in the polyrepo
         | case)
         | 
         | So: while, yes, it _would_ be a hassle to "coordinate changes
         | across repos" (though _significantly_ less to coordinate across
         | a single repo-to-repo boundary, especially if both are owned by
         | the same team, than it would to coordinate a whole monorepo's
         | worth of interactions), the joy of a polyrepo situation is that
         | _you don't have to_. Consumers can update when they want to, at
         | their own pace - no coordination necessary! So - yes, there
         | will be a greater _volume_ of PRs required in a polyrepo
         | situation, but a) each of them will be way simpler and the
         | total volume of work will be , b) they are independent (so
         | teams who don't want to update do not hold back those who do).
         | 
         | But - people keep saying "it's easier to make wide-ranging
         | changes in a monorepo", so I _must_ be missing something. What
         | is it?
         | 
         | [0] https://engineering.atspotify.com/2023/05/fleet-
         | management-a...
        
           | evntdrvn wrote:
           | What I've heard from friends working at places where the
           | monorepo model has worked well, is that it also involved a
           | culture shift such that the burden of upgrading the consuming
           | services is put on the shoulders of the _providers_ of the
           | library, rather than the consumers. This implicitly brings
           | along some benefits, like making the providers not cause
           | excessive/unnecessary version churn and ensuring easy upgrade
           | paths, because they experience the pain rather than it being
           | externalized onto the consumers :) Also, good tooling helps--
           | and I think that this model also encourages investing in
           | that.
        
             | scubbo wrote:
             | Wow, that is certainly a _huge_ culture shift. It certainly
             | explains why it's not sitting right with me - while I do
             | think that "providers not caus[ing] excessive/unnecessary
             | version churn and ensuring easy upgrade paths" is a good
             | thing in isolation, it seems like it would be massively
             | outweighed by the downsides of forcing a library provider
             | to maintain familiarity with all their consumers' codebases
             | and business areas. Seems to me like that would make it
             | impractical to make any changes to a library that is
             | consumed by more than a few other teams - which runs
             | totally contrary to the intention of extracting _commonly_-
             | depended-upon logic. The ideal situation would be to create
             | a library that is _so_ popular that maintaining that level
             | of familiarity is literally impossible.
             | 
             | There are already incentives in place to ensure that a
             | library provider is doing right by their consumers
             | (building features that they want, making upgrades not too
             | arduous), because if they make a hard-to-use library then
             | people won't use it which should show up in however their
             | team's success is judged. Seems to me that going the extra
             | mile from "you have to provide a good desirable library" to
             | "and you must also be familiar enough with your consumers'
             | services to do the integration/upgrade work _for_ them"
             | gives no new upside but all downside - service teams
             | _already_ know their domain area, why should someone else
             | have to?
             | 
             | (I recognize that you're just reporting what you've heard,
             | I'm not arguing _with you_, I'm trying to reason out the
             | arguments in my head to get them straight)
             | 
             | Really appreciate the insight, thank you!
        
       | mpweiher wrote:
       | Not just instead of a service.
       | 
       |  _Always_ write a library first.
       | 
       | Not for any specific benefits, though these exist, but for
       | architectural reasons. You can trivially wrap a library into
       | pretty much everything else, but not the other way around.
       | 
       | In fact, on macOS/iOS I put _all_ functionality in frameworks, as
       | these have structure and can thus contain other frameworks and
       | non-code resources, which is more difficult with a library.
       | 
       | https://blog.metaobject.com/2020/06/mpwtest-only-tests-frame...
        
       | denton-scratch wrote:
       | Why does Windows seem to consist largely of a _huge_ number of
       | services?
       | 
       | Why do those services seem to have names that provide precious
       | little guidance on what they are for?
        
       | rascul wrote:
       | > By library, I mean any software that can be run by the user:
       | shared objects, modules, servers, command line utilities, and
       | others. By service, I mean any software which the user can't run
       | on their own; anything which depends (usually through an API) on
       | a service provider for its functionality.
       | 
       | These seem to be odd definitions and they make the article hard
       | to reason about.
        
         | catern wrote:
         | Do you have better suggestions for what words/phrases to use to
         | refer to these two categories?
        
       | yawboakye wrote:
       | > By library, I mean any software that can be run by the user:
       | shared objects, modules, servers, command line utilities, and
       | others. By service, I mean any software which the user can't run
       | on their own; anything which depends (usually through an API) on
       | a service provider for its functionality.
       | 
       | this definition makes (open source) self-hosted services
       | libraries too, and so i think it's wrong and unusable. the
       | distinction between a library and a service is clear enough and
       | colloquial at this point that a redefinition probably obscures
       | rather than clarifies. a library isn't runnable (~has no binary),
       | a service is runnable (~has a binary)
        
         | catern wrote:
         | What do you suggest as an alternative way to express these
         | concepts?
         | 
         | Colloquially, "library" and "service" have 95% of the correct
         | connotations.
        
       | klysm wrote:
       | Even executables imo should be very thin wrappers around
       | libraries
        
       | nlawalker wrote:
       | I have a hunch that a lot of people who have been spurred to
       | think critically about this today are realizing that what they're
       | actually interested in are services (in the economic sense) and
       | not software.
        
       | sidlls wrote:
       | Libraries and services both have maintenance costs and upgrade
       | impedance from clients. The costs might differ, but in my
       | experience work out to about the same overall. The correct way to
       | determine whether a piece of software should be a library or
       | service is by examining its intended purpose and its
       | dependencies.
       | 
       | - If the software is dependent on another service or a data
       | store, it should be a service: this provides the owners freedom
       | to include error handling and observability that is appropriate
       | for the service and provides protection for its dependencies
       | against unbounded access (via observability at minimum, or human-
       | organized contracts, etc.). Examples: software to retrieve user
       | data from a database, software that aggregates data from a user
       | service and an inventory service to produce a purchase history
       | 
       | - If the software is self-contained, e.g., it does math or "pure
       | business logic" algorithms, it _probably_ should be a library:
       | performance can be optimized for one or a small handful of common
       | use cases, error handling and observability become the
       | responsibility of clients, and neither owners of the library or
       | clients of it have to concern themselves with the impact to
       | transitive dependencies (e.g., load added to a database).
       | Examples: software that transforms user input into internal
       | serialization formats; software that validates data, encrypts or
       | decrypts data, or otherwise is  "purely functional"
        
         | layer8 wrote:
         | It's not an either or. As argued elsethread, it should arguably
         | always be a library (though not necessarily a published one),
         | and optionally (if needed) also a service that wraps the
         | library.
        
       | mgaunard wrote:
       | The difference lies in deployment.
       | 
       | A library is a piece of code that you embed. A service is already
       | deployed and configured, ready to use.
       | 
       | Services provide a much nicer boundary for splitting
       | responsibilities in any SaaS-like organization.
        
         | Manouchehri wrote:
         | Agreed. Building libraries from multiple private repos is hell
         | in comparison to just having each as their own service.
        
       | Joel_Mckay wrote:
       | Indeed, because it is easy to keep updated with compatible
       | library package standards (
       | https://en.wikipedia.org/wiki/List_of_software_package_manag...
       | ).
       | 
       | Docker and Snap core use-case purpose is a necessary
       | compatibility layer. =)
        
       | eikenberry wrote:
       | 90% disagree.
       | 
       | At an enterprise scale shop the service model will always win as
       | it will better match the organization structure and avoids the
       | maintenance burden of having to keep a dozen or so libraries in
       | sync. Enterprise shops never standardize solely on a single
       | language as they are filled with exceptions and the new hotness.
       | 
       | Everyplace else I'd say it will vary but I agree with the general
       | consensus that shooting for the model of a library that can be
       | easily run as a service is your best approach.
        
         | throwbadubadu wrote:
         | But you can add the generic all problem solving run a library
         | as a service service wrapper around it and have both and be
         | done forever?
        
       | Matthias247 wrote:
       | I had the same opinion in the past. But after some more years of
       | work experience - mostly in the managed services area - I don't
       | think it's that clear anymore:
       | 
       | - If you offer your users a library, you are competing with tons
       | of open source libraries which claim to offer the same thing. A
       | lot of those will be incomplete, buggy or insecure. But most
       | potential users will never know and try to get them work instead
       | of looking at your offering.
       | 
       | - If you are offering a library, debugging and user support can
       | at times be challenging. Do you expect user to look at the
       | internals (source code) of your library? Provide core dumps?
       | 
       | - Having to support N different [major] versions of libraries can
       | become challenging. It's hard to know when all users have
       | upgraded. With a service, you can control the update schedule.
       | Even though changes to public APIs of the service certainly are
       | still problematic.
       | 
       | - Write a library - but in which language? You might prefer Rust,
       | but your users might prefer Go, Java or Python. You could write
       | the core in one language, and add wrappers in other languages,
       | but some users will still be unhappy with it (e.g. because it
       | makes compilation difficult, people don't want "unsafe C code" in
       | their high level language project, or the wrapper might slow down
       | performance).
       | 
       | - Libraries which are general-purpose and are not targetting a
       | specific application/service can over time become feature bloated
       | since things are added "just for the case that someone might need
       | it". This makes them hard to maintain. And since there's no
       | feedback/telemetry, it's also hard to say whether something can
       | be safely removed.
       | 
       | Note that all of this doesn't mean "don't write libraries". Even
       | if you write applications/services, its good to structure
       | internal components into libraries. It's mostly about "what is
       | preferrable to offer for users".
        
       ___________________________________________________________________
       (page generated 2023-11-23 23:01 UTC)