ZDT Deployment for PHP
Modern web services need to be accessible at all times. However, during project re-deployment (i.e., updates), applications can go down or return errors until the process is complete. Tools like Capistrano and Fabric can address this, but they often require additional time, expense, and specialist knowledge to integrate and configure properly. For example, setting up multiple servers with a load balancer to exclude servers during deployment can be complex and resource-intensive.
A simpler solution for PHP applications running on Apache was proposed by Rasmus Lerdorf, the creator of PHP and our technical advisor. This method, actively used at Etsy and battle-tested, forms the basis for the Zero Downtime & Atomic Deployment feature on our platform. The key points of this approach are:
1. File Duplication During Deployment:
- Each time a new deployment process is run, the application’s files are duplicated and stored in a separate server directory. This directory is automatically named based on its creation date and time for easy identification.
2. Symbolic Link (Symlink) Switching:
- A special request redirector, called a symlink (symbolic link), switches between different application versions after each update, pointing to the version that should be currently used.
In this way, the updated project files can be seamlessly deployed while the original code version continues to operate and handle user sessions. Once the deployment is fully completed, the symlink instantly switches to the latest version of the successfully deployed application, redirecting all incoming requests to it. This approach ensures that the deployment process is fully atomic and transparent to your customers, relieving you from performing numerous manual operations.
Below, we’ll explore this mechanism in more detail by describing:
- ZDT deployment workflow
- How ZDT functionality is ensured on the platform
- Atomic and classic deployment modes comparison
Let’s go on!
ZDT Deployment Workflow
First, let’s look at how the PHP zero-downtime deployment mechanism operates on the platform. We’ll examine this process step-by-step with a real example.
Step 1. Begin by setting up a PHP environment (either a new or an existing one). For this example, we’ll use Apache.
Step 2. Proceed with deploying the required application. During the deployment process, ensure to tick the appropriate checkbox in the confirmation frame (depending on the project’s source type) to enable the ZDT deployment option:
For deployment via local file or direct URL:
For deployment via VCS (e.g. from GIT/SVN or Bitbucket repo):
Note:
- The zero-downtime deployment flag becomes active only when deploying to the ROOT context of your PHP application server. Otherwise, the classic method will be used.
- When working with VCS repositories, the chosen deployment mode will be remembered and used for all further auto-updates of this application until you change it manually.
- Generally, we recommend not using “hard-coded” absolute paths in your app’s code and configs while using the atomic deployment feature to ensure it remains operative regardless of the project’s directory name.
Step 3. During the initial deployment, a folder named ROOT_timestamp (e.g., ROOT_year.mm.dd-hh.mm.ss) and a special ROOT file acting as a symlink to this folder are created inside the webroot directory of your application server.
Once the deployment process is finished, the application is ready to handle requests as usual.
Step 4. During the second deployment (i.e., when deploying an update), a new folder named ROOT_timestamp is created. This ensures that the current application version and the customers using it remain unaffected.
Immediately after the new files are unpacked, the symlink switches to this new folder, directing all newly received requests to it. Meanwhile, the first folder continues processing sessions for “old” users, i.e., those who began their session before the symlink switch.
Step 5. Subsequent atomic deployments follow the same process. Each deployment involves removing the oldest project folder while adding a new ROOT_timestamp directory for the most recent project version.
This method ensures that only two versions of the deployed application—the latest and the previous one—are stored within the app server simultaneously. The older version can be manually removed when it is no longer needed, preventing any unnecessary disk space consumption.
All operations are fully automated, requiring no additional involvement from developers. The deployment process is executed smoothly, without the need for an app server restart, ensuring zero application downtime.
ZDT Implementation at PHP Servers
The atomic deployment option for Apache PHP instances is facilitated by the mod_realdoc module. This module manages the symlink switching process and can be further configured through the platform dashboard in the conf.d > mod_realdoc.conf file.
For additional details about this module, please refer to its source page. Regarding NGINX-PHP, atomic deployment relies on built-in functionality without requiring additional modules. You can find the corresponding settings at the end of the conf > nginx.conf file. With this understanding, let’s compare both classic and atomic deployment methods.
Comparison and Summary
To demonstrate the advantages of the ZDT update approach, we conducted a straightforward load test with the following key parameters:
- Application: We used a basic version of WordPress CMS for the test, deploying its default distribution without any heavy content.
- Load Generation Tool: Apache JMeter was configured to continuously send the necessary amount of concurrent requests to our application throughout the redeployment process.
- Time Frame: The test commenced shortly before initiating the redeployment process and concluded a few seconds after its completion.
Let’s delve into the most widely used method of project deployment – the classic approach, also known as installation from a single archived package without additional features like ZDT enabled:
In this scenario, we observe commendable results:
- Swift and consistent response time (depicted by the blue graph), averaging just 1.2 seconds.
- Rapid restoration to normal operation, where all incoming requests are successfully processed (illustrated by the green line) with no encountered errors (depicted by the red graph).
- A brief spike in response time lasting only two seconds, as highlighted by the red line (though deploying a more content-rich project could potentially extend this interval).
Now, let’s conduct the identical test using the second contender – ZDT. To facilitate clearer comparison, we’ll maintain the same color legend as previously used:
The response time remains stable and nearly unchanged, albeit with a slight increase during the update process, attributed to concurrent deployment activities alongside request serving. Remarkably, no errors occur throughout the entire test duration.
Hence, zero downtime deployment effectively mitigates the issue of failed requests during application updates, while maintaining an average response time consistent. Moreover, the atomic approach affords the flexibility to retain all user-generated content within the application directory, facilitating seamless migration to the new application version as needed – a capability absent in the conventional deployment method.
VCS Deployment
Now, let’s replicate our test for the second type of deployment, which involves using version control systems (VCS) such as Git or SVN. We’ll begin with the classic deployment method:
Since the deployment sources are located in a remote repository, this process naturally takes longer compared to installing from an uploaded archive. This delay allows us to more clearly observe the differences. During this process, the response time experiences a significant drop (nearly 4 seconds in our case), indicating the unavailability of the application. This is reflected in the spike in the errors graph, indicating a failure to handle incoming requests during this period. Otherwise, the performance remains largely consistent with the previous deployment method.
Finally, the last test for ZDT deployment via VCS aligns with our expectations, maintaining a stable response time with a slight increase during simultaneous operations, such as handling user sessions and updating the project.
Additionally, no errors occurred, and all incoming requests were successfully processed.
Conclusion
Alright, we’ve delved into the technical nitty-gritty (raw data, visualizations, and practical applications) of ZDT, and you’ve witnessed its user-friendly implementation within our platform. Now, let’s condense this information and highlight the significant advantages it brings to your PHP application’s hosting environment.
- Cost-Conscious Choice: ZDT eliminates the need for additional resource allocation like separate instances or tools. You simply require sufficient disk space to store two project versions (current and previous). Compared to other solutions potentially demanding extra app servers, balancers, or external services, ZDT emerges as a practically free-of-charge option.
- Deployment Made Easy: The deployment process remains as streamlined as ever. There’s no requirement for additional configurations or manual intervention, ensuring a smooth and hassle-free experience.
- Atomic Speed and Zero Downtime: ZDT upholds its promise – deployment speed remains identical to the classic method, preventing any delays for your users. Even more importantly, ZDT lives up to its namesake by guaranteeing a completely transparent update process for your customers. This stands in stark contrast to the classic approach, which can introduce errors even during minor application deployments.
- The ZDT Advantage: By incorporating ZDT deployment, you transform project updates into a seamless and invisible operation for both your team and your customers. This empowers you to maintain optimal application performance and deliver a consistently exceptional user experience.










