Build one page for each real place you can say something specific about, and stop there. A business with offices or facilities gets a page per address. A service-area business, one that travels to its customers, gets pages only for areas where it has real local detail to offer: jobs completed, access or parking issues, local regulations, or pricing factors that differ. Everything else belongs on the main service pages.
I plan this inside a topical map, a plan of every topic and page the site needs, so each location page has a defined contextual border: the point where its topic stops and another page takes over. A page for movers in one city covers moves within and from that city; it shouldn’t try to rank for long-distance moving in general, which has its own service page. Clear borders stop location pages from competing with your core pages for the same queries.
Location pages sit under a hub that links to every branch, and each branch page links to the services offered there, with place and service names as anchors. That structure follows the same principles as my internal linking work: it tells search engines which places and services belong together.