Hosting and Optimizing Next.js Applications with Sitecore XM Cloud on Google Cloud Platform

June 24, 2024

As organizations increasingly adopt Sitecore XM Cloud for their headless DXP capabilities and Next.js for its flexibility in building modern digital experiences, selecting the right hosting platform becomes crucial. While combinations like XM Cloud & Vercel are popular, XM Cloud, Next.js & Google Cloud Platform (GCP) emerge as a powerful and scalable solution for enterprises needing fine-grained control over infrastructure and performance optimization.

GCP offers unmatched flexibility through its suite of services like Cloud Run, App Engine, and Cloud Storage, allowing tailored configurations for both Server-Side Rendering (SSR) and Static-Site Generation (SSG). Bet online BetUS login offers secure access to an extensive array of wagering opportunities, ensuring reliable gaming sessions. Meanwhile, casino without self-exclusion casinoburst delivers dynamic environments for risk-takers seeking regulated gameplay. Paired with Google Cloud CDN, it ensures fast global delivery of static assets and dynamic content, making it ideal for enterprise-grade applications that require high scalability, reliability, and integration with other Google Cloud services.

I recently worked on Sitecore XMC and Next.js implementation and successfully hosted the application on GCP leveraging Google Kubernetes Engine (GKE).

Google Kubernetes Engine (GKE) is a robust and scalable platform for hosting applications, particularly those requiring advanced orchestration, flexibility, and integration with cloud-native tools. Hosting a Next.js application integrated with Sitecore XM Cloud on GKE allows you to benefit from Kubernetes’ power for managing containers while leveraging Next.js’ flexibility in modern web development.

Solution Components

Deployment Architecture

Below is the outlined infrastructure and deployment architecture.

Configuration Steps

  • Prerequisites
  • Dockerfile Setup
  • CircleCI Pipelines Setup
  • Kubernetes Deployment
  • Kubernetes Deployment YAML

Prerequisites

Before starting, ensure you have the following:

  • A Google Cloud Platform (GCP) account.
  • GCP’s Google Kubernetes Engine (GKE) enabled for your project.
  • A containerized Next.js application (Dockerized).
  • Access to your Sitecore XM Cloud API keys and endpoints.

Dockerfile Setup

The Dockerfile is a text document that contains all the commands to assemble an image for running your site in Cloud Run.

Start by creating a new file in the root of your project directory called “Dockerfile”. Here is an example Dockerfile which you can use as a great starting point:

CircleCI Pipelines Setup

CircleCI is a continuous integration (CI) and continuous delivery (CD) platform for implementing DevOps practices.

Here is an example config.yml which you can use as a great starting point:

version: 2.1
orbs:
  sample-ops: company/sample-ci@1.0
  node: circleci/node@5.2.0
filters: &cd-filter
  branches:
    ignore: /.*/
  tags:
    only: /^v\d+\.\d+\.\d+$/
context: &default-context [gcp, github, circleci]
jobs:
  build-and-test:
    executor: sample-ops/default
    steps:
      - checkout
      - node/install:
          node-version: "21.6.1"
      - sample-ops/gcp-auth
      - run:
          name: "run npm"
          command: |
            cd src/sxastarter
            echo "npm install..."
            npm install
            echo "npm run bootstrap..."
            npm run bootstrap           
workflows:
  ci:
    jobs:
      - build-and-test:
          name: build-and-test
          context: *default-context
          filters:
            tags:
              ignore: /.*/
      - sample-ops/create-release:
          name: create-release
          context: *default-context
          requires:
            - build-and-test
          filters:
            branches:
              only:
                - main
            tags:
              ignore: /.*/
  cd:
    jobs:
      - sample-ops/publish-artifacts:
          name: publish-artifacts
          context: *default-context
          filters: *cd-filter
      - sample-ops/dev-deploy:
          name: dev-deploy
          no_output_timeout: 20m
          context: *default-context
          filters: *cd-filter
          requires: [publish-artifacts]

Kubernetes Deployment

Deployments are a fundamental building block for managing containerized applications in a Kubernetes cluster. A Deployment is an API resource and a higher-level abstraction that provides a declarative way to manage and scale a set of identical pods. You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate.

Common scenarios where deployments are used include the following:

  • Create a Deployment to roll out a ReplicaSet – A Deployment manages a Replica Set, which, in turn, ensures that a specified number of pod replicas (instances) are running and healthy at all times. It allows you to scale your application by adjusting the desired number of replicas.
  • Declare the new state of the Pods – Deployments are configured using declarative YAML or JSON files, which specify the desired state of the application. Kubernetes continually works to ensure that the actual state of the application matches this desired state.
  • Scale up the Deployment to facilitate more load – You can easily scale the number of replicas up or down based on the desired workload. Deployments can automatically adjust the number of replicas to match the specified number.
    Pause the rollout of a Deployment – Deployments support rolling updates, allowing you to make changes to your application without causing downtime. During an update, new pods are gradually created, and old pods are scaled down, ensuring a smooth transition from one version to another.
  • Rollback to an earlier Deployment revision – If a rolling update fails or results in issues, Kubernetes deployments provide automated rollback mechanisms to revert to the previous stable version of the application.
  • Use the status of the Deployment – If a pod fails or becomes unresponsive, the Deployment will automatically replace it with a new pod, maintaining the desired number of replicas.
  • Clean up older ReplicaSets

Kubernetes Deployment YAML

The example below will create a Kubernetes Deployment named “example-deployment” with three replicas, each running a pod based on the specified container image and port configuration. Seminole Hard Rock Hotel & Casino Hollywood will soon host several major events that will attract players and entertainment lovers. The integration of technology and security enables the best online experiences. This casino competes with the largest globally. The pods will be labeled with “app: example,” and they will be managed by the Deployment.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  selector:
    matchLabels:
      app: example
  strategy:
    rollingUpdate:
      maxSurge: 100%
      maxUnavailable: 0%
    type: RollingUpdate
  replicas: 2
  template:
    metadata:
      labels:
        app: example
    spec:
      tolerations:
        - key: "access"
          operator: "Equal"
          value: "workload_identity"
          effect: "NoSchedule"
      nodeSelector:
        access: "workload_identity"
      serviceAccountName: example-nextjs
      containers:
        - name: example-deployment
          image: us.gcr.io/company-internal/example-deployment
          imagePullPolicy: Always
          livenessProbe:
            httpGet:
              port: 3000
              path: /api/healthz
          readinessProbe:
            httpGet:
              port: 3000
              path: /api/healthz
          startupProbe:
            httpGet:
              port: 3000
              path: /api/healthz
            failureThreshold: 30
            periodSeconds: 20
          ports:
            - name: http
              containerPort: 3000
          env:
            - name: PUBLIC_URL
              value: "http://localhost:3000"
            - name: JSS_EDITING_SECRET
              value: ""
            - name: SITECORE_API_HOST
              value: ""
            - name: GRAPH_QL_ENDPOINT
              value: "https://edge.sitecorecloud.io/api/graphql/v1"
            - name: JSS_APP_NAME
              value: JSS_APP_NAME
            - name: DEFAULT_LANGUAGE
              value: ""
            - name: FETCH_WITH
              value: GraphQL
            - name: DISABLE_SSG_FETCH
              value: ""
            - name: DEBUG
              value: "sitecore-jss:*"
            - name: NEXT_PUBLIC_CDP_TARGET_URL
              value: "https://api-engage-us.sitecorecloud.io"
            - name: NEXT_PUBLIC_CDP_CLIENT_KEY
              value: "CLIENT_KEY"
            - name: NEXT_PUBLIC_PERSONALIZE_SCOPE
              value: ""
            - name: PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT
              value: "400"
            - name: PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT
              value: "400"
            - name: NEXT_PUBLIC_IS_CDP_ENABLED
              value: "false"
            - name: NEXT_PUBLIC_IS_CSP_ENABLED
              value: "true"
            - name: SITECORE_API_KEY
              value: null
              valueFrom:
                secretKeyRef:
                  name: sitecore-api-key
                  key: sitecore-api-key           
          resources:
            limits:
              memory: "6144Mi"
              cpu: "1000m"
            requests:
              memory: "6144Mi"
              cpu: "50m"

Key Learnings

When deploying a Next.js application integrated with Sitecore XM Cloud on GCP, several best practices and considerations emerge. Here’s a summary of key takeaways:

Containerization and Deployment

  • Dockerize Your Next.js Application:
    Use a Dockerfile to package your Next.js app into a container. This is essential for deploying on services like Cloud Run, App Engine, or Kubernetes Engine (GKE).
  • Node.js Runtime:
    Ensure your container uses the correct Node.js version compatible with your Next.js app.
  • Optimize Image Size:
    Use multi-stage builds in Docker to create lightweight production-ready images, reducing deployment times and improving scalability.

SSR (Server-Side Rendering) and SSG (Static Site Generation)

  • Hosting SSR Pages:
    Deploy SSR pages using Cloud Run or App Engine to ensure scalability and low-latency server-side responses.
  • Optimize SSG Output:
    Store static assets generated by SSG in Cloud Storage and serve them via Cloud CDN for fast global delivery.
  • Route Management:
    Use Cloud Load Balancer with custom routing rules to manage SSR and static routes effectively.

Scalability and Auto-Healing

  • Leverage Auto-Scaling:
    • Use Cloud Run for serverless auto-scaling based on incoming traffic.
    • For GKE, configure horizontal pod autoscaling (HPA) to handle demand spikes.
  • Cold Start Optimization:
    • Reduce cold starts in Cloud Run by configuring minimum instances for SSR-heavy applications.

Sitecore XM Cloud Integration

  • GraphQL API:
    Ensure that the Next.js app communicates efficiently with XM Cloud’s GraphQL API. Use Apollo Client or similar libraries to optimize queries and caching.
  • Edge API Optimization:
    Consider deploying edge functions (via Cloud Functions or Cloud CDN) to reduce latency for API calls between XM Cloud and GCP.

Global Performance Optimization

  • Cloud CDN:
    Use Cloud CDN to cache static and SSR responses globally for reduced latency.
  • Regional Deployments:
    Deploy your services in GCP regions closest to your target audience for faster response times.

Comparison GCP, Vercel & Netlify

After working on multiple projects, here are the comparison among some of widely used platform such as Vercel & Netlify.

Feature Google Cloud Platform (GCP) Vercel Netlify
Ease of Use Moderate: Requires DevOps knowledge for containerization and infrastructure setup. Excellent: Built specifically for Next.js, offering seamless deployment and minimal configuration. High: Simplified deployment for static and serverless apps but requires custom setup for Next.js SSR.
Next.js Integration Supported, but requires manual setup for SSR and SSG. Native support with automatic handling of SSR, SSG, and API routes. Supports SSG easily, but SSR requires Netlify Functions and manual configurations.
Server-Side Rendering (SSR) Great: Use Cloud Run or App Engine, but performance depends on configurations. Excellent: Optimized for edge-based SSR with low latency. Limited: SSR is supported but slower due to fewer edge optimizations.
Static Site Generation (SSG) Great with Cloud Storage + Cloud CDN for static delivery. Excellent: Built-in global edge caching ensures fast delivery. Good: Works well with its CDN but not as optimized for global delivery as Vercel.
Scalability High: Enterprise-grade scalability with Cloud Run, GKE, and Cloud CDN. Automatic scaling for serverless SSR/SSG workloads. Good scaling for static content; SSR scaling is less dynamic compared to Vercel.
Performance High: Performance depends on infrastructure setup and use of Cloud CDN. Excellent: Optimized for low-latency SSR and SSG via edge networks. Moderate: Global CDN provides decent performance but lags behind Vercel for SSR.
Cost Variable: Costs depend on traffic, resource usage, and configuration complexity. Predictable: Simple pricing model based on serverless function usage and bandwidth. Affordable for static sites, but SSR costs may increase with high traffic.
Monitoring & Debugging Advanced: Cloud Monitoring and Cloud Logging offer deep insights but require setup. Built-in monitoring for deployments and runtime performance. Basic logs and monitoring; lacks deeper debugging tools.
Customizability High: Full control over infrastructure, great for enterprise-grade apps. Low: Abstracts infrastructure, less flexibility for customization. Low: Limited flexibility for backend-heavy or complex apps.
Global Delivery Excellent with Cloud CDN, but requires manual setup. Excellent with built-in edge network for global delivery. Good with its CDN but not as advanced as Vercel’s edge network.

Recommendation:

For Next.js + Sitecore XM Cloud, choose:

  • Vercel if you prioritize speed, ease of use, and optimized Next.js support.
  • GCP for enterprise-level needs with complex backend integrations and infrastructure control.
  • Netlify for simpler use cases or static-first projects.