Getting Started
  • Introduction
  • Installation
  • About
Core Concepts
  • Routing System
  • Page Functions
  • Data Fetching
  • Server Components
  • Client Components
  • Advanced
Features
  • Dynamic & Query Parameters
  • Navigation
  • Styles & CSS
  • Assets
  • Favicons
Configuration
  • Environment Variables
  • Import Aliases
  • Ejecting
  • Deployment
dinou logodinou
docs
npmGitHub

Persisting In-Memory Values Between Renders (Dynamic Rendering)

Learn why in-memory state doesn't survive HTML rendering in dinou when rendering dynamically, and how to persist values like counters using external storage.

Overview

dinou renders HTML in a child process, isolated from the main server process. This means that any global state or in-memory variables are not shared across HTML renders. While the RSC server can retain memory, the HTML renderer cannot.

This can cause hydration mismatches if your page depends on changing in-memory values like counters.

Here's a problematic example:

// src/page_functions.ts

let counter = 0;

export function getProps() {
  return { page: { visits: counter++ } }; // ❌ This causes hydration mismatch
}

In the code above, the HTML output will always be 0, while the hydrated React app will see an incremented value.

Important: This problem arises only in dynamic rendering.

File-based Persistence

One way to persist data is through local file storage using Node.js fs APIs. Here’s an example:

import fs from 'fs';
const path = '.dinou_cache/counter.txt';

export function getCounter(): number {
  let value = 0;
  if (fs.existsSync(path)) value = parseInt(fs.readFileSync(path, 'utf8'), 10);
  fs.writeFileSync(path, String(value + 1));
  return value;
}

Redis-based Persistence

You can also use Redis, a fast in-memory data store. This is especially useful in distributed or serverless environments.

import { createClient } from 'redis';
const redis = createClient();
await redis.connect();

export async function getCounter() {
  const key = 'dinou:counter';
  const val = await redis.get(key);
  const num = val ? parseInt(val) : 0;
  await redis.set(key, num + 1);
  return num;
}

You can use Upstash for a serverless Redis-compatible database.

Best Practices

  • Avoid using in-memory state in getProps() or revalidate() unless it's fully deterministic.
  • If you need state persistence, rely on external systems like the file system, Redis, or a database.
  • Document any assumptions your code makes about state between renders.

On This Page

OverviewFile-based PersistenceRedis-based PersistenceBest Practices