Getting screwed works both ways. I know I'd uncomfortable paying the final invoice before receiving the final source code deployed and working. What's stopping the developer from never quite getting around sort out the final deployment after I've handed over all my money. I know people who've experienced more or less just that.
Perhaps there is a market for some sort of third party source code escrow service, for software contractors.
Excellent question. As a developer, I suggest asking for everything. But some clients have asked this exact same question, and two things that have worked for me have been:
1. Agree on a %-age of the money as a 'hold back.' The client pays within a set period, e.g. 30 days, if there have been no problems or when all problems are resolved. I wouldn't agree to more than 10% hold-back, personally, but it isn't a big issue.
2. Agree that for each deliverable, there is a milestone for "accepted" where the client tests it on your development or acceptance system, and another for "deployed." There is a payment for each milestone. There could be other milestones leading up to "acceptance," of course, and there would be payments for each of these.
Perhaps there is a market for some sort of third party source code escrow service, for software contractors.