Microservices buy independent deployment and pay for it with a network between every call. Modules give you the boundaries first, for free.
Most of the benefit people attribute to microservices comes from having explicit module boundaries — one owner per aggregate, no shared tables, communication through a published contract. All of that is achievable in a single deployable.
When one module genuinely needs its own scale or release cadence, the in-process handler becomes a queue consumer. The calling code already goes through the contract, so extraction is a transport swap rather than a rewrite.
type Matcher interface {
Match(ctx context.Context, resumeID string) ([]Job, error)
}
// in-process today, HTTP or queue tomorrow — callers do not changeSplit for an organizational or scaling reason you can name. "Cleaner architecture" is not one.