Improve performance of React Server Side Render by warming up service

Background

We’re using ElasticBeanstalk Blue/Green deployment by swapping DNS, and in front of the deployed services, there’s a company level Nginx to forward requests to different services.
The TTL of DNS entry set to 1 minute, and Nginx will cache the resolved name entries until it expired. Each time after we deploy, all the requests hit the new environment after the DNS cache expired in Nginx.

React Server Render time without warming up

The response time increases a lot in the following a couple of minutes and becomes stable after 5 minutes. Because the response time impacted by upstream services, it’s better to analyze and improve react server render time which is a sync method call and not involve IO operations.

Here’s the initial reactServerRender time for Home Page and Search Result Page:


For the Home page, it took 2-3 minutes for the reactRender time reduced from 450 – 550 ms to 120 ms


For the Search Result page, it took 1-2 minutes for the reactRender time reduced from 700 – 750 ms to 230 ms

Warm up React render after server started

In the Elastic Load Balancer, we mark the EC2 instance as active after 3 consecutive successful requests with 10 seconds interval. Which means we’ll always need to wait at least 30 seconds after server started listening.

    HealthCheckPath: /_healthcheck
    HealthCheckInterval: '10'
    HealthyThresholdCount: '3'

During this 30 seconds startup time, we can warm up reactRender to improve service response time. Here’s the example code to call react server render to render Home Page 10 times and Search Result Page 5 times.

app.listen(port, () => {
  if(warmupEnabled) {
    warmup({
      serverRender,
      paths: [
        { appPath: '/', interval: 500, limit: 10 },
        { appPath: '/jobs', interval: 500, limit: 5 }
      ]
    });
  }
})

In my local dev environment, with the above changes, the render time of Home page reduced from 1 second to 50 ms and Search Result Page reduced from 1 second to 150 ms.

Everything looks good, and let’s deploy to production and check the metrics again


For the Home page, it took 20 seconds for the reactRender time reduced from 350 – 375 ms to 170 ms and another 20 seconds to 150 ms

For the Search Result page, it took 40 seconds for the reactRender time reduced from 500 – 550 ms to 230 ms

The good thing is the warm up approach worked and it reduced the reactRender time, but not enough, so let’s do more warm ups:

  • Increase the serverRender of Home page to 30 times, and by changing the interval to 300 ms, we can control the whole warm up will be finished in 30 seconds which will not impact on the real requests.
  • Render the search result page only 5 times to keep minimum impacts on upstream services
app.listen(port, () => {
  if(warmupEnabled) {
    warmup({
      serverRender,
      paths: [
        { appPath: '/', interval: 300, limit: 30 },
        { appPath: '/jobs', interval: 500, limit: 5 }
      ]
    });
  }
})

Deploy and check the metrics again:


For the Home page, except a couple of exceptions, it took 30 seconds for the reactRender time reduced from 165 ms to 120 ms.

For the Search Result page, it took 5 seconds for the reactRender time reduced from 300 – 350 ms to 200 ms

Average react server render impacts of deployment

Without warm up

  • Max render time of Home page increased from 55 ms to 72 ms
  • Max render time of Search Result page increased from 110-120 ms to 150-160ms

After warm up

  • Max render time of both Home page and Search Result page increased 10 ms

Conclusion

Without warm up

  • Home page: it took 2-3 minutes for the reactRender time reduced from 450 – 550 ms to 120 ms
  • Search Result page: it took 1-2 minutes for the reactRender time reduced from 700 – 750 ms to 230 ms

After warm up

  • Home page: it took 30 seconds for the reactRender time reduced from 165 ms to 120 ms
  • Search Result page: it took 5 seconds for the reactRender time reduced from 300 – 350 ms to 200 ms

On a average 10 deployments per day, in case of 6000 requests per minute, warming up improves response time for 6000 * 3 * 10 = 180,000 requests per day.

Leave a Reply

Your email address will not be published. Required fields are marked *