Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zero downtime/blue-green deployment of Single Page Application (SPA)

Yesterday together with the team we were discussing the possibility of using zero downtime deployments to support our single page application.

While discussing it we identified one edge case for it. After user loads the page in his browser it cannot be removed from memory until he reloads the page. It means that if user loads the page and starts working with the website (for example starts typing a long article like I am doing now) then he cannot receive an updated version of it until he reloads the page.

We could ignore the fact that user sees old application version in his browser but there 2 points listed below.

  1. In case we introduce a breaking change to HTTP Api that is used to serve spa then the user will not be able to save his article (data loss!) or can receive some other error when performing other backend related action.
  2. When user navigates to a new page without reloading SPA he can receive a template of the next page or of some control that is incompatible with outer old container. It can kead to broken markup or application logic.
  3. We cannot force user to relogin as he can be in the middle of typing his article and it is just a bad UX.

Taking all theses points into account one could propose the following solution:

  1. User 1 loads v1 of the SPA into his browser.
  2. Alongside with auth token the version information is sent to browser (using JWT for example).
  3. We want to deploy v2 version of our application. We spin up the v2 version but do not disable v1.
  4. User 2 loads v2 of SPA into his browser
  5. User 1 goes to the next page in SPA. Load balancer checks the version information in his token and routes the traffic of the user 1 to v1 server.
  6. User 2 gets routed in the same way to v2.
  7. User 1 logs out the app and closes the browser.
  8. User 1 logs in back - this time he receives v2.
  9. After v1 application does not receive any traffic for a long time it gets disposed.

In this approach however it is possible to have multiple versions alive, more than 2 (for example if user stays online for whe whole day or two). It means that we will not be able to migrate the database to the new schema until the last user gets logged out (image how it could work for sites like Facebook). It is not a problem to have multiple versions however, such tools as Docker and Rancher allow us to do it easily.

Also in the step 7. User needs to reload the page or close the browser-otherwise he still will be working with v1 and we cannot force him to the next version.

The question I have is what approach do you use to do zero downtime/blue-green deployment of single page applications?

How do you manage the lifetime of "blue" version of your application when you are switching traffic to "green" version, especially in respect to existing "blue" client applications.

Did you solve these issues, do you know any other solution?

like image 800
gerichhome Avatar asked Oct 05 '16 04:10

gerichhome


People also ask

Is blue-green deployment zero downtime?

The Blue-Green deployment strategy is a relatively simple technique that provides zero downtime deployment and a safe way to test the code before sending production traffic to it. It can be implemented as the final deployment solution or as a first step towards more complex techniques like Canary deployments.

What are zero downtime deployments?

Zero downtime deployment is a deployment method where your website or application is never down or in an unstable state during the deployment process. To achieve this the web server doesn't start serving the changed code until the entire deployment process is complete.

What is blue-green deployment technique?

A blue/green deployment is a deployment strategy in which you create two separate, but identical environments. One environment (blue) is running the current application version and one environment (green) is running the new application version.


2 Answers

I've been struggling with this problem for quite some time and tried several approaches and one specifically worked really well:

  • Use hashed names when bundling the SPA (including images, et al)
  • Use a static asset bucket (e.g.: AWS S3) and upload all assets to it before the deployment process kicks in
  • Enforce internal guidelines to minimize API contracts to be broken (i.e: fields from an endpoint should only be removed after X releases)
  • Deploy with usual blue/green strategy

Rationale

Using a bucket with hashed bundles ensures that if a customer gets the old version of the SPA, all of its assets will be available before/during/after any deployment process. Enforcing internal guidelines to not break API compatibility is sometimes tricky but it comes from the very same principles applied to any public API. Embracing/adapting an API deprecation policy from big players helps when communicating with the team with a concrete example.

like image 128
Erick Wilder Avatar answered Oct 03 '22 11:10

Erick Wilder


One approach you might consider is gradual reloading of the SPA in such a moment, when it is not burdensome (or even unnoticeable) for end user.

Suggested approach:

Colored versions of the system (components providing back-end services, API and front-end) "know" (runtimes are provided with) their "color". Component providing users with front-end application embeds this color information into the SPA. This is then sent (via cookie or custom HTTP header) with every request SPA is making to the backend.

Component that routes API calls (API gateway, load balancer, nginx, HAproxy, custom Zuul-based router etc) is aware of this color information and uses it to direct traffic to infrastructure of proper color.

Additionally there is a public URL (not provided by "colored" infrastructure - for example S3 file provided via CloudFront or other proxy) with latest version color. SPA is checking this version every given period of time (60 or 120 seconds). If version does not match the one SPA was provided when loading then on the major next route change page is reloaded "physically", instead of realizing this navigation in browser only.

You can choose which route changes are verifying this version in such a way that it is least obtrusive to the user (possibly almost unnoticeable).

If you choose some of the routes that are used every day by all users then pretty soon all users will migrate to the latest color. Those who have unused opened browser window for long periods of time (computer hibernated for two weeks?) can be handled by forcing reload after certain period of inactivity.

I hope I managed to make myself sound at last a bit cohesive :-)

Regards, Wojtek

like image 40
wciesiel Avatar answered Oct 03 '22 12:10

wciesiel