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

# .NET SDK - Caching Behaviour

> When does the .NET SDK hit the network, snapshot atomicity, and ETag/304.

The SDK keeps every config / secret / flag in an **in-memory snapshot** that is replaced atomically as a whole on each sync. Reads never block on the network; only the periodic background refresh does.

## When does the SDK hit the network

| Event                             | Result                                                                              |
| --------------------------------- | ----------------------------------------------------------------------------------- |
| `NexusClient.CreateAsync(...)`    | **Blocking** full sync. The constructor only resolves once the cache is populated.  |
| Read within the TTL window        | **No network** - served from the in-memory cache                                    |
| Read after TTL has elapsed        | Stale cache returned **immediately**; one background refresh fires in parallel      |
| Server returns `304 Not Modified` | TTL reset, no payload downloaded                                                    |
| Multiple concurrent expirations   | Only **one** background sync runs at a time (`Interlocked` guard)                   |
| SSE event received                | Immediate full sync, regardless of TTL                                              |
| SSE stream connected              | Effective TTL bumped to **60 s** as a safety net (the stream handles fresh updates) |

## The atomic snapshot guarantee

The snapshot is replaced as one immutable record. Two reads from different threads either see the same old state or the same new state - never a mix.

```csharp theme={null}
var a = client.GetConfig("a");   // sees snapshot N
// ... some other thread triggers a sync ...
var b = client.GetConfig("b");   // sees snapshot N+1 (or still N - but always consistent)
```

This means you can iterate `GetAllConfigs()` without worrying about an entry being added or removed mid-loop.

## ETag / 304

Every successful sync stores the server's `ETag`. The next sync sends `If-None-Match: <etag>`. If nothing has changed:

```
HTTP/1.1 304 Not Modified
```

...the SDK resets its `SyncedAt` timestamp and serves the existing snapshot. **No payload transferred.**

## Background sync errors

Background syncs **never throw**. If the network call fails:

1. The error is logged via `INexusLogger.Error(...)`
2. The existing cache continues to be served
3. The next read after the TTL elapses retries automatically

## Cache lifetime

The cache lives as long as the `NexusClient` instance. Disposing the client (or letting it be garbage-collected) releases the memory. Typical use is **one singleton client per application**, registered with DI; do not create per-request.

## Diagnostics

| Property                   | What it tells you                                                  |
| -------------------------- | ------------------------------------------------------------------ |
| `client.SyncedAt`          | When was the last successful sync - useful for "Last refreshed" UI |
| `client.IsStreamConnected` | Is the SSE stream currently up                                     |
| `client.KeyType`           | `"sk"` or `"pk"` - confirms the SDK saw the right key prefix       |

Logging `INexusLogger.Debug` will emit one line per sync:

```
nexus: sync OK - configs=12 secrets=4 flags=7 key_type=sk
nexus: sync 304 Not Modified - cache retained
```
