The technique of copying the new version to an unused folder and then changing the PhysicalPath of the VirtualDirectory achieves an atomic deployment of the *web app* but there is no way to synchronize changes to the database to guarantee that the "old version" of the web app only sees the "old version" of the database whilst the "new version" only sees the new version.
This is because IIS starts forwarding HTTP requests to the new AppDomain whilst the old AppDomain continues to finish processing requests.
I have a working technique that uses a named mutex to "hold back" HTTP requests for the new AppDomain.
But this causes http clients to receive errors in the event of a deployment rollback, because new HTTP requests have already been forwarded to the new AppDomain ... there is no way to "push them back"
Now I am thinking the only solution is to develop a native core module that can hold HTTP requests *before* they are assigned to an Application Pool.
How do others achieve this (without load balancers, etc.)