Your problem was using JSON instead of a typed language like Protocol Buffers or even Java RPCs, and that you were using separate repos for everything.
Microservices don't even have to run in separate binaries, let along separate machines.
Which is actually much better than a distributed monolith (random microservices thrown together just because it ticks some boxes on managements resumes)
Agreed! I think a well-structured monolith is what most projects call for.
What I don't want is for people to buy the microservices hype so thoroughly that they start thinking "microservices" just means "well-architected system".
If you have a single deployment unit, you have a monolith, regardless of how that deployment unit is structured on the inside. There's a lot of fuzziness about what "microservices" means, but some degree of independent deployability is pretty non-negotiable.
Microservices don't even have to run in separate binaries, let along separate machines.