Use retry strategies for requests to Experience Edge

Version: 22.x

The Experience Edge GraphQL endpoint is rate-limited, meaning there is a limit on the number of requests that can be made within a specific time frame (currently 80 requests per second). While building or deploying a large Next.js application with static generation (SSG) enabled, you might hit that limit, causing the build process to fail.

At build time, the Next.js application sends requests to the endpoint through multiple services. You can implement retry strategies and specify the number of retries (either globally or for each service) to successfully generate the production code for a large website.

Note

Retry strategies are available in JSS version 20 from 20.3 onwards and in version 21 from 21.6.3 onwards.

Set the number of retries

You can configure a specific number of retries globally or per service.

Set the number of retries globally

Next.js JSS applications use the GRAPH_QL_SERVICE_RETRIES environment variable to set the number of GraphQL request retries for all services that use a GraphQL endpoint (the Layout, Dictionary, and Error Page services). Retries are initially set to 3 based on the default value of the environment variable. You can disable retries for all services by setting that value to 0.

To set the number of retries globally:

  • Update the value of the GRAPH_QL_SERVICE_RETRIES environment variable to the desired value (a positive integer, or 0 to disable).

Set the number of retries per service

If you want to specify a different number of retries for each service, you can either set the value of each service's retries option to a positive integer or 0, or define custom environment variables for each service. In either case, make changes to the following files as needed:

  • For the Layout service: src/lib/layout-service-factory.ts.

  • For the Dictionary service: src/lib/dictionary-service-factory.ts.

  • For the Error Page service: src/pages/404.tsx and src/pages/500.tsx.

Note

If you add environment variables or modify the value of GRAPH_QL_SERVICE_RETRIES, remember to make the necessary changes in your deployment platform, testing pipelines, and so on.

Modify the default retry strategy

If you've set the number of retries to a positive integer, the affected services will use a default retry strategy based on that number, with an exponential back-off/delay factor of 2.

The default retry strategy handles the following response status codes:

  • 429 - too many requests.

  • 502 - 504 - server errors.

  • 520 - 524 - Edge-specific errors.

It also supports the following error codes:

  • ECONNRESET - connection reset error

  • ETIMEDOUT - timeout error

  • EPROTO - protocol error

You can modify the default strategy's list of status codes, error codes, and back-off/delay factor as needed.

To modify the default retry strategy:

  1. In your service factory file, for example, /src/lib/dictionary-service-factory.ts, import the DefaultRetryStrategy class:

    RequestResponse
     import {
      DefaultRetryStrategy
    } from '@sitecore-jss/sitecore-jss-nextjs';
  2. In the GraphQL service options, modify the default retry strategy configuration by specifying the desired error codes, status codes, and delay factor. If the default configuration is not present, you will need to add it first. For example:

    RequestResponse
    retries:
      (process.env.GRAPH_QL_SERVICE_RETRIES &&
       parseInt(process.env.GRAPH_QL_SERVICE_RETRIES, 10)) ||
      0,
      retryStrategy: new DefaultRetryStrategy({ statusCodes: [402, 409]; errorCodes: ['ENOTFOUND', 'ETIMEDOUT']; factor: 1})

Create a custom strategy

If you want to customize the retry strategy beyond status codes, error codes, and delay factor, you can implement your own retry strategy class based on the RetryStrategy interface.

The interface defines a strategy for retrying GraphQL requests based on errors and attempts. It defines two methods as follows:

  • shouldRetry - determines whether a request should be retried based on the error and attempt count. It returns a Boolean value, and requires the following parameters:

    Parameter

    Description

    error 

    The error of the GraphQLClientError type received from the GraphQL request. The GraphQLClientError type handles both ClientError and NodeJS.ErrornoException types.

    retries 

    The number of retries configured.

    Default: 3

    attempt 

    The current attempt number.

  • getDelay - calculates the delay (in milliseconds) before the next retry, based on the given error and attempt count. It returns the delay for the next retry in milliseconds, and requires the following parameters:

    Parameter

    Description

    error 

    The error of the GraphQLClientError type received from the GraphQL request. The GraphQLClientError type handles both ClientError and NodeJS.ErrornoException types.

    attempt 

    The current attempt number.

To create a custom retry strategy:

  1. In your service factory file, for example, /src/lib/dictionary-service-factory.ts, import the RetryStrategy interface:

    RequestResponse
    import {
      RetryStrategy,
      ClientError,
      GraphQLClientError,
    } from '@sitecore-jss/sitecore-jss-nextjs';
  2. Declare a new constant of the RetryStrategy type and implement the shouldRetry and getDelay methods. For example:

    RequestResponse
    const customRetryStrategy: RetryStrategy = {
      shouldRetry: (error: GraphQLClientError, retries: number, attempt: number): boolean => true, // Replace this with your own implementation
      getDelay: (error: GraphQLClientError, attempt: number): number => 1000 // Replace this with your own implementation
    };
  3. Add your custom retry strategy to the GraphQL service options. For example:

    RequestResponse
    new GraphQLDictionaryService({
      siteName,
      clientFactory,
      retries:
        (process.env.GRAPH_QL_SERVICE_RETRIES &&
          parseInt(process.env.GRAPH_QL_SERVICE_RETRIES, 10)) ||
        0,
      retryStrategy: customRetryStrategy
    }) 

Do you have some feedback for us?

If you have suggestions for improving this article,