# RPC Replay Policy in Magnitude: Choosing Between replaySafe and atMostOnce

> Understand Magnitude's RPC replay policy. Learn when to use replaySafe versus atMostOnce to manage remote calls and prevent duplicate side effects after disconnections.

- Repository: [Magnitude/magnitude](https://github.com/magnitudedev/magnitude)
- Tags: deep-dive
- Published: 2026-09-08

---

**Magnitude's RPC layer classifies every remote call with a replay policy that determines whether the operation can be safely re-executed after disconnection or must run exactly once to prevent duplicate side effects.**

The `magnitudedev/magnitude` repository implements a resilient RPC protocol through its **acn-protocol** package, where each remote procedure call is tagged with a specific RPC replay policy. These policies control how the system handles client reconnections and request retries, ensuring reliable communication between the ACN daemon and its clients while maintaining data consistency.

## Understanding the Two RPC Replay Policies

Magnitude provides two distinct recovery strategies generated by the `withRecovery` helper in [`packages/acn-protocol/src/transport/recovery.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/transport/recovery.ts). Each policy creates an Effect pipe that attaches specific retry behavior to the underlying RPC stream.

### replaySafe for Idempotent Operations

The `replaySafe` policy wraps RPC calls that can be **safely replayed** without causing inconsistencies or harmful side effects. This policy attaches a recovery strategy that automatically re-executes the call if the connection drops, making it ideal for read-only operations. Use this policy for state synchronization calls, configuration reads, or listing resources where fetching the same data twice poses no risk.

According to the source code, the session listing RPC in [`packages/acn-protocol/src/boundary/sessions.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/sessions.ts) uses this policy because querying available sessions is purely idempotent.

### atMostOnce for Side-Effectful Actions

The `atMostOnce` policy ensures operations execute **no more than once**, even when network interruptions occur. This policy prevents automatic retries, forcing the client to explicitly handle recovery when failures happen. Apply this to mutating operations like creating sessions, writing files, deleting resources, or committing changes where duplicate execution would create data corruption or redundant resources.

The boundary implementations in [`packages/acn-protocol/src/boundary/files.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/files.ts) demonstrate this by applying `atMostOnce` to file write and delete operations while using `replaySafe` for reads.

## Implementation in the Transport Layer

In [`packages/acn-protocol/src/transport/recovery.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/transport/recovery.ts), the `withRecovery` helper function constructs Effect pipes that bind the chosen recovery strategy to RPC streams. This transport-level abstraction allows the boundary layer to declaratively specify execution guarantees before exposing functionality through the SDK in `packages/sdk`.

The policy selection happens at the boundary layer, where public RPC methods are constructed by piping underlying streams through either `replaySafe` or `atMostOnce` before reaching client-facing APIs.

## Boundary Layer Policy Applications

### Session Management (boundary/sessions.ts)

The sessions boundary in [`packages/acn-protocol/src/boundary/sessions.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/sessions.ts) illustrates clear policy separation. The **session-list** RPC uses `replaySafe` because fetching session data is idempotent and safe to repeat. Conversely, the **session-create** RPC uses `atMostOnce` to prevent duplicate session creation if the network drops during the request.

### File Operations (boundary/files.ts)

Similarly, [`packages/acn-protocol/src/boundary/files.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/files.ts) applies `replaySafe` to file read operations but enforces `atMostOnce` for write and delete calls. This distinction protects against data corruption when network interruptions occur during file mutations.

### Project Operations (boundary/projects.ts)

The projects boundary in [`packages/acn-protocol/src/boundary/projects.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/projects.ts) demonstrates mixed usage, applying `replaySafe` to project listing and retrieval while reserving `atMostOnce` for project creation and modification calls.

## Practical Usage Examples

Apply these policies by piping RPC streams through the recovery helpers from the transport layer:

```typescript
import { pipe } from "@effect/data/Function";
import { replaySafe, atMostOnce } from "@magnitudedev/acn-protocol/transport/recovery";

// Safe to replay: read-only operation
export const listProjects = pipe(
  rpc.listProjects,
  replaySafe
);

// Must execute once: side-effectful operation
export const createProject = pipe(
  rpc.createProject,
  atMostOnce
);

```

When consuming through the SDK layer, these policies operate transparently:

```typescript
import { AgentClient } from "@magnitudedev/sdk";

// Internally uses replaySafe (packages/acn-protocol/src/boundary/projects.ts)
await AgentClient.listProjects();

// Internally uses atMostOnce 
await AgentClient.createProject({ name: "demo" });

```

## Summary

- **RPC replay policy** determines how Magnitude handles request retries after disconnections in the acn-protocol transport layer.
- **`replaySafe`** in [`packages/acn-protocol/src/transport/recovery.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/transport/recovery.ts) permits automatic re-execution for idempotent reads and queries.
- **`atMostOnce`** prevents duplicate execution for mutating operations like session creation or file writes.
- The `withRecovery` helper attaches these policies at the boundary layer (e.g., [`boundary/sessions.ts`](https://github.com/magnitudedev/magnitude/blob/main/boundary/sessions.ts), [`boundary/files.ts`](https://github.com/magnitudedev/magnitude/blob/main/boundary/files.ts)) before SDK exposure.
- Consistent policy application ensures the ACN daemon maintains correctness during network instability.

## Frequently Asked Questions

### What happens if I use replaySafe on a mutating RPC?

Using `replaySafe` on side-effectful operations risks duplicate execution if the client reconnects during a request. Since this policy automatically retries failed requests without client intervention, a partially completed mutation could run twice, causing data inconsistencies or duplicate resources in the system.

### How does atMostOnce handle network failures?

When a network failure occurs during an `atMostOnce` call, the system prevents automatic retry and surfaces the error to the client. The client must then explicitly decide whether to retry, often requiring application-level checks to verify whether the previous attempt succeeded before attempting recovery.

### Where are these policies defined in the source code?

Both policies are implemented in [`packages/acn-protocol/src/transport/recovery.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/transport/recovery.ts) through the `withRecovery` helper function. This module creates Effect pipes that wrap underlying RPC streams with the appropriate recovery strategy, which are then applied in boundary files like [`packages/acn-protocol/src/boundary/sessions.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/sessions.ts) and [`packages/acn-protocol/src/boundary/files.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/files.ts).

### Can I change the replay policy for existing RPC methods?

While the built-in boundary implementations follow strict conventions distinguishing reads from writes, custom RPC implementations can specify either policy when constructing the Effect pipe. However, changing from `atMostOnce` to `replaySafe` requires verifying the operation is truly idempotent, as automatic retries on non-idempotent calls violate the correctness guarantees of the ACN protocol.