Atomic symlink swaps

By Michael Williams, Published on 10/07/2018

When changing symlinks, particularly as part as a deployment. The goal is generally to eliminate downtime. We often refer to these an atomic deployments.
Just because you are using a symlink those, doesn't necessarily mean your deployment is atomic. Lets dive a bit deeper into this.

By definition, in concurrent programming an operation would be considered atomic if it appears to the rest of the system to occur at once without being interrupted.

Assuming for simplicity we setup the following symlink:

ln -sf release current

Listing that directory as expected would show

ls -lah current -> release

Now we want to point our update code to current. By practice may would run the following: ln -snf update current. Lets run an strace over that and look at the output.

strace ln -snf update current  2>&1 | grep link symlink("update", "current") = -1 EEXIST (File exists) unlink("current") = 0 symlink("update", "current") = 0

As you can see this does not occur at once, but instead in two parts. The initial symlink is first removed, then the new link is created. We can get around this though by following a different process. First we will create a new symlink and rename the old.

ln -sf update current.tmp && mv -Tf current.tmp current symlink("update", "current.tmp") = 0

Finally, listing the directory:

ls -lah current -> update

As expected our code is pointing to the updated directory.