---
description:
  Performance is a critical aspect of any application. Hive Gateway Runtime provides a set of
  features to help you optimize the performance of your gateway.
searchable: false
---

import { Callout } from '@theguild/components'

# Performance & Caching

Hive Gateway provides a set of features to help you optimize the performance of your GraphQL
gateway. Hive Gateway provides a shared caching storage that can be used across plugins, transforms,
subgraph execution and remote schema caching.

<Callout>
  If you are running Hive Gateway [serverless on the edge](/docs/gateway/deployment/serverless),
  you're highly advised to provide a cache. Aside from all of the aforementioned benefits, the
  biggest one is caching the remote schema so that it does not get pulled on each request.
</Callout>

## Providing Cache Storage

In order to enable features that need a storage to keep the data, you need to define a cache storage
implementation, and pass it to the gateway.

You can choose the best-fit cache storage for your use case.

### LocalForage

LocalForage is a library that improves the existing storage mechanism in the browser by using
`IndexedDB`, `WebSQL` and `localStorage`, [see more](https://github.com/localForage/localForage).

Even if it is known as a browser storage, Hive Gateway provides you as a platform-agnostic cache
storage to leverage the well-known storage APIs that are available in most JavaScript environments.

```ts filename="gateway.config.ts"
import { defineConfig } from '@graphql-hive/gateway'

export const gatewayConfig = defineConfig({
  cache: {
    type: 'localforage',
    // All of the following options are listed with default values, you don't need to provide them
    driver: ['WEBSQL', 'INDEXEDDB', 'LOCALSTORAGE'] // The order of the drivers to use
    name: 'HiveGateway', // The name of the database
    version: 1.0, // The version of the database
    size: 4980736, // The size of the database
    storeName: 'keyvaluepairs', // The name of the store
    description: 'Cache storage for Hive Gateway', // The description of the database
  }
  responseCaching: {
    session: () => null,
  }
})
```

### Redis

Redis is an in-memory data structure store, used as a database, cache, and message broker. You can
use Redis as a cache storage for your Hive Gateway.

<Callout>The Redis cache currently only works in Node.js environments.</Callout>

```ts filename="gateway.config.ts"
import { defineConfig } from '@graphql-hive/gateway'

export const gatewayConfig = defineConfig({
  cache: {
    type: 'redis',
    host: 'localhost', // The host of the Redis server
    port: 6379, // The port of the Redis server
    password: undefined, // The password of the Redis server
    lazyConnect: true, // If true, the connection will be established when the first operation is executed
    // or
    url: 'redis://localhost:6379' // The URL of the Redis server
  },
  responseCaching: {
    session: () => null
  }
})
```

### Cloudflare Workers KV

Cloudflare Workers KV is a distributed, eventually consistent key-value store available in the
Cloudflare Workers runtime. You can use Cloudflare Workers KV as a cache storage for your Hive
Gateway. [Learn more about KV here.](https://developers.cloudflare.com/workers/runtime-apis/kv/)

<Callout>
  This is only available for Cloudflare Workers runtime. If you want to learn how to deploy your
  Hive Gateway to Cloudflare Workers, you can check the [deployment
  documentation](/docs/gateway/deployment/serverless/cloudflare-workers).
</Callout>

```ts filename="worker.ts"
import { createGatewayRuntime } from '@graphql-hive/gateway-runtime'
import CloudflareKVCacheStorage from '@graphql-mesh/cache-cfw-kv'
import supergraph from './my-remote-supergraph-config'

export default {
  fetch(request, env, ctx) {
    const gateway = createGatewayRuntime({
      supergraph,
      transports: { http },
      responseCaching: {
        session: () => null
      },
      cache: new CloudflareKVCacheStorage({
        logger,
        namespace: env.NAMESPACE
      })
    })
    ctx.waitUntil(gateway[Symbol.asyncDispose]())
    return gateway(request, env, ctx)
  }
}
```

## Custom Cache Storage

You can also implement your own cache storage by extending the `CacheStorage` class. It needs to
match `KeyValueCache` interface from `@graphql-hive/gateway`.

```ts filename="my-cache-storage.ts"
import { LRUCache } from 'lru-cache'
import { KeyValueCache } from '@graphql-hive/gateway'

export class MyKeyValueCache<V = any> implements KeyValueCache<V> {
  // Your cache implementation here
  private cache = new LRUCache<string, V>()

  // Get the value of the key
  async get(key: string) {
    return this.cache.get(key)
  }

  // Set the key with the value and optional options
  async set(key: string, value: V, options?: { ttl?: number }) {
    this.cache.set(key, value, options?.ttl)
  }

  // Delete the key from the cache
  async delete(key: string) {
    this.cache.del(key)
  }

  // Get all keys that match the given prefix
  async getKeysByPrefix(prefix: string) {
    return Array.from(this.cache.keys()).filter(key => key.startsWith(prefix))
  }

  // This should be implemented if you want to clear the cache on shutdown
  [Symbol.asyncDispose]() {
    this.cache.reset()
  }
}
```
