> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Redis (Object cache)

export const DynamicCodeBlock = ({language = 'yaml', filename, icon, lines, wrap, expandable, highlight, focus, children}) => {
  const STORAGE_KEY = 'upsun_versions_cache';
  const COMPOSABLE_STORAGE_KEY = 'upsun_composable_cache';
  const CACHE_TTL = 5 * 60 * 1000;
  const API_URL = 'https://meta.upsun.com/images';
  const COMPOSABLE_API_URL = 'https://meta.upsun.com/composable';
  const DEBUG_PREFIX = '[DynamicCodeBlock cache]';
  const [versionData, setVersionData] = useState(null);
  const [versionError, setVersionError] = useState(false);
  const [composableData, setComposableData] = useState(null);
  const [composableError, setComposableError] = useState(false);
  useEffect(() => {
    const fetchData = async () => {
      let cachedData = null;
      let cachedEtag = null;
      if (typeof localStorage !== 'undefined') {
        try {
          const cached = localStorage.getItem(STORAGE_KEY);
          if (cached) {
            const parsed = JSON.parse(cached);
            cachedData = parsed?.data || null;
            cachedEtag = parsed?.etag || null;
            if (cachedData && Date.now() - parsed.timestamp < CACHE_TTL) {
              return cachedData;
            }
          }
        } catch (err) {
          console.error('Failed to load from cache:', err);
        }
      }
      const requestHeaders = cachedEtag ? {
        'If-None-Match': cachedEtag
      } : {};
      console.debug(`${DEBUG_PREFIX} revalidating`, {
        storageKey: STORAGE_KEY,
        hasCachedData: Boolean(cachedData),
        hasCachedEtag: Boolean(cachedEtag)
      });
      const response = await fetch(API_URL, {
        headers: requestHeaders
      });
      if (response.status === 304 && cachedData) {
        console.debug(`${DEBUG_PREFIX} revalidated (304)`, {
          storageKey: STORAGE_KEY
        });
        if (typeof localStorage !== 'undefined') {
          try {
            const etag = response.headers.get('etag') || cachedEtag;
            localStorage.setItem(STORAGE_KEY, JSON.stringify({
              data: cachedData,
              etag,
              timestamp: Date.now()
            }));
          } catch (err) {
            console.error('Failed to refresh cache metadata:', err);
          }
        }
        return cachedData;
      }
      if (!response.ok) throw new Error(`API request failed: ${response.statusText}`);
      const data = await response.json();
      const etag = response.headers.get('etag');
      console.debug(`${DEBUG_PREFIX} refreshed (200)`, {
        storageKey: STORAGE_KEY,
        etag
      });
      if (typeof localStorage !== 'undefined') {
        try {
          localStorage.setItem(STORAGE_KEY, JSON.stringify({
            data,
            etag,
            timestamp: Date.now()
          }));
        } catch (err) {
          console.error('Failed to cache data:', err);
        }
      }
      return data;
    };
    fetchData().then(data => setVersionData(data)).catch(err => console.error('Failed to fetch version data:', err));
  }, []);
  const findHighestVersion = versionsMap => {
    if (!versionsMap || Object.keys(versionsMap).length === 0) return null;
    const entries = Object.entries(versionsMap);
    const active = entries.filter(([, v]) => v.upsun && v.upsun.status === 'supported' || v.upsun && v.upsun.status === 'deprecated');
    const candidates = active.length > 0 ? active : entries;
    let [highestName] = candidates[0];
    for (let i = 1; i < candidates.length; i++) {
      const [currentName] = candidates[i];
      const cp = currentName.split('.').map(Number);
      const hp = highestName.split('.').map(Number);
      for (let j = 0; j < Math.max(cp.length, hp.length); j++) {
        if ((cp[j] || 0) > (hp[j] || 0)) {
          highestName = currentName;
          break;
        } else if ((cp[j] || 0) < (hp[j] || 0)) {
          break;
        }
      }
    }
    return highestName;
  };
  const getVersion = (lang, requestedVersion = 'latest') => {
    if (lang === 'composable') {
      if (!composableData || !composableData.versions || Object.keys(composableData.versions).length === 0) return null;
      if (requestedVersion && requestedVersion !== 'latest') {
        return (requestedVersion in composableData.versions) ? requestedVersion : null;
      }
      return findHighestVersion(composableData.versions);
    }
    if (!versionData) return null;
    const imageData = versionData[lang];
    if (!imageData || !imageData.versions || Object.keys(imageData.versions).length === 0) {
      return null;
    }
    if (requestedVersion && requestedVersion !== 'latest') {
      return (requestedVersion in imageData.versions) ? requestedVersion : null;
    }
    return findHighestVersion(imageData.versions);
  };
  let code = typeof children === 'string' ? children : String(children || '');
  const codeLines = code.split('\n');
  while (codeLines.length > 0 && codeLines[0].trim() === '') codeLines.shift();
  while (codeLines.length > 0 && codeLines[codeLines.length - 1].trim() === '') codeLines.pop();
  if (codeLines.length > 0) {
    const indents = codeLines.filter(line => line.trim().length > 0).map(line => line.match(/^[ \t]*/)[0].length);
    const minIndent = Math.min(...indents);
    code = codeLines.map(line => line.slice(minIndent)).join('\n');
  }
  code = code.replace(/\{\{version:(.*?)\}\}/g, (match, params) => {
    const parts = params.split(':');
    const lang = parts[0];
    const ver = parts[1] || 'latest';
    const isComposable = lang === 'composable';
    const hasError = isComposable ? composableError : versionError;
    const dataReady = isComposable ? composableData !== null : versionData !== null;
    if (hasError) return '(unavailable)';
    if (dataReady) {
      const resolvedVersion = getVersion(lang, ver);
      return resolvedVersion || match;
    }
    return '...';
  });
  const codeBlockProps = {
    language,
    ...filename && ({
      filename
    }),
    ...icon && ({
      icon
    }),
    ...lines !== undefined && ({
      lines
    }),
    ...wrap !== undefined && ({
      wrap
    }),
    ...expandable !== undefined && ({
      expandable
    }),
    ...highlight && ({
      highlight
    }),
    ...focus && ({
      focus
    })
  };
  return <CodeBlock {...codeBlockProps}>{code}</CodeBlock>;
};

[Redis](https://redis.io/documentation) is a multi-model database that allows you to store data in memory
for high-performance data retrieval and key-value storage.
Upsun supports two different Redis configurations:

* [Persistent](#persistent-redis): to set up fast persistent storage for your application
* [Ephemeral](#ephemeral-redis): to set up a non-persistent cache for your application

## Supported versions

You can select the major and minor version.

Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.

* <span class="runtime-version-badge" data-tooltip="version: 8.0.6">8.0</span>

## Deprecated versions

The following versions are still available in your projects,
but they're at their end of life and are no longer receiving security updates from upstream.

* <span class="runtime-version-badge" data-tooltip="version: 7.2.14">7.2</span>
* <span class="runtime-version-badge" data-tooltip="version: 6.2.21">6.2</span>

To ensure your project remains stable in the future, switch to a [supported version](#supported-versions).

## Retired versions

The following versions have been retired and are no longer available.
If your project uses a retired version, you must update to a [supported version](#supported-versions).

* <span class="runtime-version-badge" data-tooltip="version: 7.0.15">7.0</span>
* <span class="runtime-version-badge" data-tooltip="version: 6.0.20">6.0</span>
* <span class="runtime-version-badge" data-tooltip="version: 5.0.14">5.0</span>

Note that versions 3.0 and higher support up to 64 different databases per instance of the service,
while Redis 2.8 only supports a single database.

## Service types

Depending on your needs,
you can set up Redis as [persistent](#persistent-redis) or [ephemeral](#ephemeral-redis).

## Relationship reference

For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the `$<RELATIONSHIP-NAME>_<SERVICE-PROPERTY>` format.

Here is example information available through the [service environment variables](/docs/development/variables#service-environment-variables) themselves,
or through the [`PLATFORM_RELATIONSHIPS` environment variable](/docs/development/variables/use-variables#use-provided-variables).

<Tabs>
  <Tab title="Service environment variables">
    You can obtain the complete list of available service environment variables in your app container by running `upsun ssh env`.

    Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/docs/development/variables#service-environment-variables) directly rather than hard coding any values.

    <DynamicCodeBlock language="bash">
      {`
              REDIS_USERNAME=
              REDIS_SCHEME=redis
              REDIS_SERVICE=redis
              REDIS_FRAGMENT=
              REDIS_IP=123.456.78.90
              REDIS_EPOCH=0
              REDIS_HOSTNAME=azertyuiopqsdfghjklm.redis.service._.eu-1.platformsh.site
              REDIS_PORT=6379
              REDIS_CLUSTER=azertyuiopqsdf-main-afdwftq
              REDIS_HOST=rediscache.internal
              REDIS_REL=redis
              REDIS_PATH=
              REDIS_QUERY={}
              REDIS_PASSWORD=
              REDIS_TYPE=redis:{{version:redis:latest}}
              REDIS_PUBLIC=false
              REDIS_HOST_MAPPED=false
            `
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="`PLATFORM_RELATIONSHIPS` environment variable">
    For some advanced use cases, you can use the [`PLATFORM_RELATIONSHIPS` environment variable](/docs/development/variables/use-variables#use-provided-variables).
    The structure of the `PLATFORM_RELATIONSHIPS` environment variable can be obtained by running `upsun relationships` in your terminal:

    <DynamicCodeBlock language="json">
      {`
              {
                "username": null,
                "scheme": "redis",
                "service": "redis",
                "fragment": null,
                "ip": "123.456.78.90",
                "hostname": "azertyuiopqsdfghjklm.redis.service._.eu-1.platformsh.site",
                "port": 6379,
                "cluster": "azertyuiopqsdf-main-7rqtwti",
                "host": "redis.internal",
                "rel": "redis",
                "path": null,
                "query": [],
                "password": null,
                "type": "redis:{{version:redis:latest}}",
                "public": false,
                "host_mapped": false
              }
            `
          }
    </DynamicCodeBlock>

    Here is an example of how to gather [`PLATFORM_RELATIONSHIPS` environment variable](/docs/development/variables/use-variables#use-provided-variables) information in a [`.environment` file](/docs/development/variables/set-variables#when-to-use-env-files):

    ```bash .environment theme={null}
    # Decode the built-in credentials object variable.
    export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)"

    # Set environment variables for individual credentials.
    export APP_REDIS_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.redis[0].host')"
    ```
  </Tab>
</Tabs>

The format of the relationship is identical whether your Redis service is [ephemeral](#ephemeral-redis) or [persistent](#persistent-redis).

## Persistent Redis

By default, Redis is an ephemeral service that stores data in memory.
This allows for fast data retrieval,
but also means data can be lost when a container is moved or shut down.

To solve this issue, configure your Redis service as persistent.
Persistent Redis stores data on a disk,
restoring it if the container restarts.

To switch from persistent to ephemeral Redis,
set up a new service with a different name.

<Warning>
  <h4>Warning</h4>
  Upsun sets the maximum amount of memory (`maxmemory`) Redis can use for the data set,
  and it cannot be amended.
  It is defined by comparing the following values and keeping the lower of the two:

  * Disk size / 2
  * Container memory × 0.75

  For example:

  * 1024 MB disk, 1024 MB memory → `maxmemory` = 512 MB
    *(disk/2 = 512, lower than 1024 × 0.75 = 768)*
  * 6144 MB disk, 1024 MB memory → `maxmemory` = 768 MB
    *(memory × 0.75 = 768, lower than 6144/2 = 3072)*
</Warning>

### Usage example

#### 1. Configure the service

To define the service, use the `redis-persistent` endpoint:

<DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
  {`
      services:
        # The name of the service container. Must be unique within a project.
        <SERVICE_NAME>:
          type: redis-persistent:<VERSION>
    `
  }
</DynamicCodeBlock>

Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.

#### 2. Define the relationship

To define the relationship, use the `redis` endpoint :

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <SERVICE_NAME>:
            `
          }
    </DynamicCodeBlock>

    You can define `SERVICE_NAME` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.

    The example above leverages [default endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](/docs/configure-apps/image-properties/relationships) (the network address a service is accessible from) that is identical to the name of that service.

    Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](/docs/configure-apps/image-properties/relationships).

    With the above definition, the application container now has [access to the service](#use-in-app) via the relationship `SERVICE_NAME` and its corresponding [service environment variables](/docs/development/variables#service-environment-variables).
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename="Using explicit endpoints .upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <RELATIONSHIP_NAME>:
                      service: <SERVICE_NAME>
                      endpoint: redis
            `
          }
    </DynamicCodeBlock>

    You can define `SERVICE_NAME` and `<RELATIONSHIP_NAME>` as you like, so long as it's unique between all defined services and relationships
    and matches in both the application and services configuration.

    The example above leverages [explicit endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships.

    Depending on your needs, instead of explicit endpoint configuration,
    you can use [default endpoint configuration](/docs/configure-apps/image-properties/relationships).

    With the above definition, the application container now has [access to the service](#use-in-app) via the relationship `<RELATIONSHIP_NAME>` and its corresponding [service environment variables](/docs/development/variables#service-environment-variables).
  </Tab>
</Tabs>

For PHP, enable the [extension](/docs/languages/php/extensions) for the service:

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis
                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <SERVICE_NAME>:
            `
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # PHP extensions.
                  runtime:
                    extensions:
                        - redis
                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <RELATIONSHIP_NAME>:
                      service: <SERVICE_NAME>
                      endpoint: redis
            `
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

### Configuration example

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
              services:
                  # The name of the service container. Must be unique within a project.
                  redis:
                    type: redis-persistent:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
                      service: redis
                      endpoint: redis
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis-persistent:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

### Use in app

To use the configured service in your app, add a configuration file similar to the following to your project.

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  [...]

                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis-persistent:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  [...]

                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
                      service: redis
                      endpoint: redis
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis-persistent:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

This configuration defines a single application (`myapp`), whose source code exists in the `<PROJECT_ROOT>/myapp` directory.<br />
`myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships).

From this, `myapp` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).

```bash myapp/.environment theme={null}
# Set environment variables for individual credentials.
# For more information, please visit /docs/development/variables#service-environment-variables.
export CACHE_HOST="${REDIS_HOST}"
export CACHE_PORT="${REDIS_PORT}"
export CACHE_PASSWORD="${REDIS_PASSWORD}"
export CACHE_SCHEME="${REDIS_SCHEME}"

# Surface a Redis connection string for use in app.
export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}"
```

The above file — `.environment` in the `myapp` directory — is automatically sourced by Upsun into the runtime environment, so that the variable `CACHE_URL` can be used within the application to connect to the service.

Note that `CACHE_URL`, and all Upsun [service environment variables](/docs/development/variables#service-environment-variables) like `REDIS_HOST`,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.

A file very similar to this is generated automatically for your when using the `upsun ify` command to [migrate a codebase to Upsun](/docs/get-started).

## Ephemeral Redis

By default, Redis is an ephemeral service that serves as a non-persistent cache.
Ephemeral Redis stores data only in memory and requires no disk space.
When the service reaches its memory limit, it triggers a cache cleanup.
To customize those cache cleanups, set up an [eviction policy](#eviction-policy).

Make sure your app doesn't rely on ephemeral Redis for persistent storage as it can cause issues.
For example, if a container is moved during region maintenance,
the `deploy` and `post_deploy` hooks don't run and an app that treats the cache as permanent shows errors.

To prevent data from getting lost when a container is moved or shut down,
you can use the [persistent Redis](#persistent-redis) configuration.
Persistent Redis provides a cache with persistent storage.

### Usage example

#### 1. Configure the service

To define the service, use the `redis` endpoint:

<DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
  {`
      services:
        # The name of the service container. Must be unique within a project.
        <SERVICE_NAME>:
          type: redis:<VERSION>
    `
  }
</DynamicCodeBlock>

Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.

#### 2. Define the relationship

To define the relationship, use the `redis` endpoint :

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <SERVICE_NAME>:
            `
          }
    </DynamicCodeBlock>

    You can define `SERVICE_NAME` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.

    The example above leverages [default endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](/docs/configure-apps/image-properties/relationships) (the network address a service is accessible from) that is identical to the name of that service.

    Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](/docs/configure-apps/image-properties/relationships).

    With the above definition, the application container now has [access to the service](#use-in-app) via the relationship `SERVICE_NAME` and its corresponding [service environment variables](/docs/development/variables#service-environment-variables).
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename="Using explicit endpoints .upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <RELATIONSHIP_NAME>:
                      service: <SERVICE_NAME>
                      endpoint: redis
            `
          }
    </DynamicCodeBlock>

    You can define `SERVICE_NAME` and `<RELATIONSHIP_NAME>` as you like, so long as it's unique between all defined services and relationships
    and matches in both the application and services configuration.

    The example above leverages [explicit endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships.

    Depending on your needs, instead of explicit endpoint configuration,
    you can use [default endpoint configuration](/docs/configure-apps/image-properties/relationships).

    With the above definition, the application container now has [access to the service](#use-in-app) via the relationship `<RELATIONSHIP_NAME>` and its corresponding [service environment variables](/docs/development/variables#service-environment-variables).
  </Tab>
</Tabs>

For PHP, enable the [extension](/docs/languages/php/extensions) for the service:

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                   # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <SERVICE_NAME>:
              services:
                # The name of the service container. Must be unique within a project.
                <SERVICE_NAME>:
                  type: redis:<VERSION>
            `
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                <APP_NAME>:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    <RELATIONSHIP_NAME>:
                      service: <SERVICE_NAME>
                      endpoint: redis
              services:
                # The name of the service container. Must be unique within a project.
                <SERVICE_NAME>:
                  type: redis:<VERSION>
            `
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

### Configuration example

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                   # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
                      service: redis
                      endpoint: redis
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

### Use in app

To use the configured service in your app, add a configuration file similar to the following to your project.

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis
                  # Relationships enable access from this app to a given service.
                  # The example below shows simplified configuration leveraging a default service
                  # (identified from the relationship name) and a default endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  [...]

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis
                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redis:
                      service: redis
                      endpoint: redis
              services:
                # The name of the service container. Must be unique within a project.
                redis:
                  type: redis:{{version:redis:latest}}`
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

This configuration defines a single application (`myapp`), whose source code exists in the `<PROJECT_ROOT>/myapp` directory.<br />
`myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/docs/configure-apps/image-properties/relationships) configuration for relationships).

From this, `myapp` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).

```bash myapp/.environment theme={null}
# Set environment variables for individual credentials.
# For more information, please visit /docs/development/variables#service-environment-variables.
export CACHE_HOST="${REDIS_HOST}"
export CACHE_PORT="${REDIS_PORT}"
export CACHE_PASSWORD="${REDIS_PASSWORD}"
export CACHE_SCHEME="${REDIS_SCHEME}"

# Surface a Redis connection string for use in app.
export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}"
```

The above file — `.environment` in the `myapp` directory — is automatically sourced by Upsun into the runtime environment, so that the variable `CACHE_URL` can be used within the application to connect to the service.

Note that `CACHE_URL`, and all Upsun [service environment variables](/docs/development/variables#service-environment-variables) like `REDIS_HOST`,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.

A file very similar to this is generated automatically for your when using the `upsun ify` command to [migrate a codebase to Upsun](/docs/get-started).

## Multiple databases

Redis 3.0 and above support up to 64 databases.
But you can't set up different access rights to each database.
When you set up a relationship connection,
access to all of the databases is automatically granted.

The way to access a particular database depends on the [client library](https://redis.io/clients) you're using:

<Tabs>
  <Tab title="PHP">
    Use the Redis [`select` command](https://redis.io/commands/select):

    ```php theme={null}
    <?php
    $redis = new Redis();
    $redis->connect(getenv('REDIS_HOST'), getenv('REDIS_PORT'));

    $redis->select(0);       // switch to DB 0
    $redis->set('x', '42');  // write 42 to x
    $redis->move('x', 1);    // move to DB 1
    $redis->select(1);       // switch to DB 1
    $redis->get('x');        // returns 42
    ```
  </Tab>

  <Tab title="Python">
    To manage [thread safety](https://github.com/redis/redis-py/blob/master/docs/advanced_features.rst#user-content-a-note-about-threading),
    the Python library suggests using separate client instances for each database:

    ```python theme={null}
    import os
    from redis import Redis

    database0 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=0)
    database1 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=1)
    ```
  </Tab>

  <Tab title="Node.js">
    Use the Redis [`select` command](https://redis.io/commands/select):

    ```javascript theme={null}
    const redis = require('redis');

    const client = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST);

    await client.SELECT(0);                  // switch to DB 0
    await client.set('x', '42');             // write 42 to x
    await client.MOVE('x', 1);               // move to DB 1
    await client.SELECT(1);                  // switch to DB 1
    const value = await client.get('x');     // returns 42
    ```
  </Tab>
</Tabs>

## Eviction policy

When Redis reaches its memory limit,
it triggers a cache cleanup.
To customize those cache cleanups, set up an eviction policy such as the following:

<DynamicCodeBlock language="yaml">
  {`
      services:
        # The name of the service container. Must be unique within a project.
        redis:
          type: "redis:{{version:redis:latest}}"
          configuration:
            maxmemory_policy: allkeys-lfu`
  }
</DynamicCodeBlock>

The following table presents the possible values:

| Value             | Policy description                                                                                          |
| ----------------- | ----------------------------------------------------------------------------------------------------------- |
| `allkeys-lru`     | Removes the oldest cache items first. This is the default policy when `maxmemory_policy` isn't set.         |
| `noeviction`      | New items aren’t saved when the memory limit is reached.                                                    |
| `allkeys-lfu`     | Removes least frequently used cache items first.                                                            |
| `volatile-lru`    | Removes least recently used cache items with the `expire` field set to `true`.                              |
| `volatile-lfu`    | Removes least frequently used cache items with the `expire` field set to `true`.                            |
| `allkeys-random`  | Randomly removes cache items to make room for new data.                                                     |
| `volatile-random` | Randomly removes cache items with the `expire` field set to `true`.                                         |
| `volatile-ttl`    | Removes cache items with the `expire` field set to `true` and the shortest remaining `time-to -live` value. |

For more information on the different policies,
see the official [Redis documentation](https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/).

## Access your Redis service

After you've [configured your Redis service](#usage-example),
you can access it using either the Upsun CLI
or through the [Redis CLI](https://redis.io/docs/latest/operate/rs/references/cli-utilities/).

### Upsun CLI

Unlike the Redis CLI, connecting via the Upsun CLI does not require additional authentication steps if you are already authenticated in your terminal.

Access your Redis service by running the command:

```bash theme={null}
upsun redis
```

### Redis CLI

Retrieve the hostname and port you can connect to
through the `PLATFORM_RELATIONSHIPS` [environment variable](/docs/development/variables/use-variables#use-provided-variables).
To do so, run the `upsun relationships` command.

After you've retrieved the hostname and port, [open an SSH session](/docs/development/ssh).
To access your Redis service, run the following command:

<DynamicCodeBlock language="bash" filename="Access your Redis service">
  {
    `
    redis-cli -h <HOSTNAME> -p <PORT>
    `}
</DynamicCodeBlock>

If you have a Grid project, note that the `CONFIG GET` and `CONFIG SET` admin commands are restricted.
To get the current configuration, run the following command:

<DynamicCodeBlock language="bash" filename="Info">
  {
    `
    redis-cli -h <HOSTNAME> -p <PORT> info
    `}
</DynamicCodeBlock>

## Use Redis as a handler for PHP sessions

A PHP session allows you to store different data for each user through a unique session ID.
By default, PHP handles sessions using files.
But you can use Redis as a session handler,
which means Redis stores and retrieves the data saved into sessions.

To set up Redis as your session handler, add a configuration similar to the following:

<Tabs>
  <Tab title="Using default endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  type: "php:{{version:php:latest}}"

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  relationships:
                    redissession:

                  variables:
                    php:
                      session.save_handler: redis
                      session.save_path: "tcp://\${REDISSESSION_HOST}:\${SESSIONSTORAGE_PORT}"

                  web:
                    locations:
                      '/':
                        root: 'web'
                        passthru: '/index.php'

              services:
                # The name of the service container. Must be unique within a project.
                redissession:
                  type: "redis-persistent:{{version:redis:latest}}"`
          }
    </DynamicCodeBlock>
  </Tab>

  <Tab title="Using explicit endpoints">
    <DynamicCodeBlock language="yaml" filename=".upsun/config.yaml">
      {`
              applications:
                # The name of the app container. Must be unique within a project.
                myapp:
                  source:
                    root: "myapp"

                  type: "php:{{version:php:latest}}"

                  # PHP extensions.
                  runtime:
                    extensions:
                      - redis

                  # Relationships enable access from this app to a given service.
                  # The example below shows configuration with an explicitly set service name and endpoint.
                  # See the Application reference for all options for defining relationships and endpoints.
                  relationships:
                    redissession:
                      service: redissession
                      endpoint: redis

                  variables:
                    php:
                      session.save_handler: redis
                      session.save_path: "tcp://\${REDISSSESSION_HOSTNAME}:\${REDISSSESSION_PORT}>"

                  web:
                    locations:
                      '/':
                        root: 'web'
                        passthru: '/index.php'

              services:
                # The name of the service container. Must be unique within a project.
                redissession:
                  type: "redis-persistent:{{version:redis:latest}}"`
          }
    </DynamicCodeBlock>
  </Tab>
</Tabs>

## Exporting Data Persistent

This section applies only to **persistent** Redis services configured with `type: redis-persistent`.
Ephemeral Redis (`type: redis`) stores data only in memory; its data does not need to be exported.

The recommended approach is to use the `BGSAVE` command to write a point-in-time RDB snapshot to disk,
then download it.

1. Open an SSH tunnel:

```bash Terminal theme={null}
upsun tunnel:single --relationship <RELATIONSHIP_NAME>
```

2. Trigger a background save and wait for it to complete:

```bash Terminal theme={null}
redis-cli -h 127.0.0.1 -p 30000 BGSAVE
# Poll until "Background saving terminated" appears:
redis-cli -h 127.0.0.1 -p 30000 LASTSAVE
```

3. Download the RDB dump file from the container:

```bash Terminal theme={null}
# Connect via SSH and locate the dump file
upsun ssh -- find / -name "dump.rdb" 2>/dev/null

# Copy it locally
upsun scp remote:/path/to/dump.rdb ./redis-dump.rdb
```

The `.rdb` file can be imported into any Redis or Valkey instance by placing it in the data directory
and restarting the service.
