# Set up Garnet in the AppHost

<Image
  src={garnetIcon}
  alt="Garnet logo"
  width={100}
  height={100}
  class:list={'float-inline-left icon'}
  data-zoom-off
/>

This article is the reference for the Aspire Garnet Hosting integration. It enumerates the AppHost APIs — with examples for both `AppHost.cs` and `apphost.mts` — that you use to model a Garnet resource in your [`AppHost`](/get-started/app-host/) project.

If you're new to the Garnet integration, start with the [Get started with Garnet integrations](/integrations/caching/garnet/garnet-get-started/) guide. For how consuming apps read the connection information this page exposes, see [Connect to Garnet](../garnet-connect/).

## Installation

To start building an Aspire app that uses Garnet, install the [📦 Aspire.Hosting.Garnet](https://www.nuget.org/packages/Aspire.Hosting.Garnet) NuGet package:

```bash title="Terminal"
aspire add garnet
```

<LearnMore>
  Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference.
</LearnMore>

Or, choose a manual installation approach:

```csharp title="C# — AppHost.cs"
#:package Aspire.Hosting.Garnet@*
```

```xml title="XML — AppHost.csproj"
<PackageReference Include="Aspire.Hosting.Garnet" Version="*" />
```

```bash title="Terminal"
aspire add garnet
```

<LearnMore>
  Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference.
</LearnMore>

This updates your `aspire.config.json` with the Garnet hosting integration package:

```json title="aspire.config.json" ins={3}
{
  "packages": {
    "Aspire.Hosting.Garnet": "13.3.0"
  }
}
```

## Add Garnet resource

Once you've installed the hosting integration in your AppHost project, you can add a Garnet resource as shown in the following examples:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddGarnet("cache");

var exampleProject = builder.AddProject<Projects.ExampleProject>("apiservice")
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts"
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const cache = await builder.addGarnet("cache");

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
```
1. When Aspire adds a container image to the AppHost, as shown in the preceding example with the `ghcr.io/microsoft/garnet` image, it creates a new Garnet instance on your local machine.

1. The Garnet resource is configured with a randomly generated password by default. To set an explicit password, see [Add Garnet resource with parameters](#add-garnet-resource-with-parameters).

1. The AppHost reference call configures a connection in the consuming project named after the referenced Garnet resource, such as `cache` in the preceding example.
**Note:** When you reference a Garnet resource from the AppHost, Aspire makes several properties available to the consuming project, such as connection URIs, hostnames, port numbers, and the password. For a complete list of these properties and per-language connection examples, see [Connect to Garnet](../garnet-connect/).

## Add Garnet resource with data volume

Add a data volume to the Garnet resource as shown in the following examples:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddGarnet("cache")
    .WithDataVolume(isReadOnly: false);

var exampleProject = builder.AddProject<Projects.ExampleProject>()
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts" twoslash
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const cache = await builder.addGarnet("cache");
await cache.withDataVolume({ isReadOnly: false });

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
```
The data volume is used to persist Garnet data outside the lifecycle of its container. The data volume is mounted at the `/data` path in the Garnet container, and when a `name` parameter isn't provided, the name is generated at random. Calling `WithDataVolume` (or `withDataVolume`) also enables Garnet persistence so the in-memory state survives container restarts. For more information on data volumes and details on why they're preferred over [bind mounts](#add-garnet-resource-with-data-bind-mount), see [Docker docs: Volumes](https://docs.docker.com/engine/storage/volumes).

## Add Garnet resource with data bind mount

Add a data bind mount to the Garnet resource as shown in the following examples:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddGarnet("cache")
    .WithDataBindMount(
        source: "/Garnet/Data",
        isReadOnly: false);

var exampleProject = builder.AddProject<Projects.ExampleProject>()
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts" twoslash
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const cache = await builder.addGarnet("cache");
await cache.withDataBindMount("/Garnet/Data", { isReadOnly: false });

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
```
**Note:** Data [bind mounts](https://docs.docker.com/engine/storage/bind-mounts/) have limited functionality compared to [volumes](https://docs.docker.com/engine/storage/volumes/), which offer better performance, portability, and security, making them more suitable for production environments. However, bind mounts allow direct access and modification of files on the host system, ideal for development and testing where real-time changes are needed.

Data bind mounts rely on the host machine's filesystem to persist Garnet data across container restarts. The data bind mount is mounted at the `C:\Garnet\Data` on Windows (or `/Garnet/Data` on Unix) path on the host machine in the Garnet container. As with `WithDataVolume`, this call also enables persistence. For more information on data bind mounts, see [Docker docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts).

## Add Garnet resource with persistence

To configure Garnet snapshot persistence explicitly, call `WithPersistence` (or `withPersistence`) alongside a data volume or bind mount:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddGarnet("cache")
    .WithDataVolume()
    .WithPersistence(
        interval: TimeSpan.FromMinutes(5),
        keysChangedThreshold: 100);

var exampleProject = builder.AddProject<Projects.ExampleProject>()
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts" twoslash
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const cache = await builder.addGarnet("cache");
await cache.withDataVolume();
await cache.withPersistence({
    interval: 5 * 60 * 1000,
});

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
```
The preceding code adds explicit persistence to the Garnet resource by snapshotting data at the configured interval. The C# AppHost accepts a `TimeSpan` for `interval` and a `keysChangedThreshold` to also trigger snapshots when a minimum number of keys change; the TypeScript AppHost accepts the interval as milliseconds.

:::note
The TypeScript `WithPersistenceOptions` does not currently expose `keysChangedThreshold`. If you need threshold-based snapshotting, use the C# AppHost.
:::

## Add Garnet resource with parameters

When you want to explicitly provide the port and password used by the Garnet container, you can pass them as parameters:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var password = builder.AddParameter("password", secret: true);

var cache = builder.AddGarnet("cache", port: 6379, password: password);

var exampleProject = builder.AddProject<Projects.ExampleProject>()
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.mts" twoslash
import { createBuilder } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const password = await builder.addParameter("password", { secret: true });

const cache = await builder.addGarnet("cache", { port: 6379, password });

await builder.addNodeApp("api", "./api", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
```
When no `password` parameter is provided, Aspire generates a strong password automatically using the `CreateDefaultPasswordParameter` method.

## Pass custom environment variables

By default, Aspire injects the Garnet connection information using variable names derived from the resource name (for example, `CACHE_URI`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_PASSWORD`). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddGarnet("cache");

var app = builder.AddExecutable("my-app", "node", "app.js", ".")
    .WithReference(cache)
    .WithEnvironment(context =>
    {
        context.EnvironmentVariables["GARNET_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host);
        context.EnvironmentVariables["GARNET_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port);
        context.EnvironmentVariables["GARNET_PASSWORD"] = cache.Resource.PasswordParameter;
    });

builder.Build().Run();
```
```typescript title="TypeScript — apphost.mts" twoslash
import { createBuilder, EndpointProperty } from './.aspire/modules/aspire.mjs';

const builder = await createBuilder();

const cache = await builder.addGarnet("cache");
const cacheEndpoint = await cache.getEndpoint("tcp");
const cacheHost = await cacheEndpoint.property(EndpointProperty.Host);
const cachePort = await cacheEndpoint.property(EndpointProperty.Port);

await builder.addNodeApp("my-app", "./app", "index.js")
    .withReference(cache)
    .withEnvironment("GARNET_HOST", cacheHost)
    .withEnvironment("GARNET_PORT", cachePort)
    .withEnvironment("GARNET_PASSWORD", await cache.passwordParameter());

await builder.build().run();
```
## Connect to an existing Garnet instance

To reference an externally managed Garnet instance instead of running one as a container, use `AddConnectionString`:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddConnectionString("cache");

var exampleProject = builder.AddProject<Projects.ExampleProject>()
    .WithReference(cache);

// After adding all resources, run the app...
```
```typescript title="TypeScript — apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

const cache = await builder.addConnectionString("cache");

await builder.addNodeApp("my-app", "./app", "index.js")
    .withReference(cache);

// After adding all resources, run the app...
await builder.build().run();
```
With `AddConnectionString` and `addConnectionString`, Aspire resolves `cache` from `ConnectionStrings:cache` (or environment variable `ConnectionStrings__cache`) in the AppHost configuration. Consuming apps receive that value as a single connection string, not deconstructed Garnet resource-specific connection-property variables such as `CACHE_HOST`, `CACHE_PORT`, or `CACHE_URI`.

## Connection properties

For the full reference of Garnet resource connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see [Connect to Garnet](../garnet-connect/).

## Hosting integration health checks

The Garnet hosting integration automatically adds a health check for the Garnet resource. The health check verifies that the Garnet instance is running and that a connection can be established to it.

The hosting integration relies on the [📦 AspNetCore.HealthChecks.Redis](https://www.nuget.org/packages/AspNetCore.HealthChecks.Redis) NuGet package, which works for Garnet because it speaks the Redis serialization protocol.