At the same time, developers run a local Vagrant VM that is configured identically to the production/staging clusters, and can run every single app (controlled using the same deployment tool). We also made it simple to mount an app you're working on, with code hotloading automatically taken care of. If you want to work on a microservice or an app, you just modify the code on your local machine and reload the page (or do an API request).
It works really well. It's not perfect, though. Since we're deploying directly to the servers, every node has to install packages, compile modules, package assets, etc., and everything has to wait on the slowest node; we'd like to transition to a system where we build a "release tarball" (or even a Docker image) once, and then push it to the cluster. Also, we're looking into using something like Mesos to better orchestrate apps and move away from role-based nodes; Puppet is way too rigid and too "opsy"; we'd like to use Puppet for controlling the base OS, and let the microservice/apps world be more dynamic.