- 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"