A function call becomes a network call. Slower by orders of magnitude (microseconds become milliseconds, at best), and now it can fail in ways a function call simply can't — a timeout, the other service being down, a partial success where some of a multi-step operation completed and some didn't. Code that used to be a guaranteed, synchronous call now needs retry logic, timeout handling, and a plan for "what if this never comes back."
No more cross-service transactions. A monolith's single database can wrap "debit this account, credit that one" in one ACID transaction, guaranteeing both happen or neither does. Across services with separate databases, that guarantee is gone — you're into eventual consistency and patterns like the Saga pattern (below) instead of a guarantee that both operations succeed together.
Distributed debugging. A single user request might now touch five services — tracing what actually happened requires centralized logging and distributed tracing (correlation IDs threaded through every call), infrastructure a monolith never needed because a stack trace inside one process was always enough.
Operational overhead. Five services means five things to deploy, monitor, version, and keep patched, versus one — each with its own CI pipeline (see CI/CD Pipelines Explained), its own container image (see Docker Fundamentals), and its own on-call surface area.
Testing gets harder. A monolith's integration tests can spin up one process and test real interactions between modules directly. Testing a real interaction between two services now means running both (or convincingly faking one), and a bug that only reproduces when two specific service versions interact a specific way is a category of bug a monolith doesn't have at all.