tag:github.com,2008:https://github.com/rocicorp/replicache/releasesRelease notes from replicache2022-04-22T05:21:23Ztag:github.com,2008:Repository/267187299/v10.0.02022-05-09T09:53:41Zv10.0.0: š General Availability š<h1>šĀ Summary</h1>
<p>After more than 2 years of development and iteration with customers, we are extremely pleased to share the first <em><strong>General Availability</strong></em> (non-beta) release of Replicache.</p>
<p>This marks the point at which we recommend Replicache for use in production systems.</p>
<p>To install:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="npm upgrade replicache-react && npm install replicache@v10.0.0"><pre>npm upgrade replicache-react <span class="pl-k">&&</span> npm install replicache@v10.0.0</pre></div>
<h2>Important: Replicache Now Requires a License Key</h2>
<p>Getting a key is easy ā run the command below and follow the prompts.</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="npx replicache@10.0.0 get-license"><pre>npx replicache@10.0.0 get-license</pre></div>
<p>For details on pricing see <a href="https://replicache.dev/#price" rel="nofollow">Commercial Pricing</a>. For details on how the licensing system works, see the <a href="https://doc.replicache.dev/licensing" rel="nofollow">Licensing Documentation</a>.</p>
<h2>License Change</h2>
<p>Together with General Availability, we are moving from the BSL license (a middle ground between open and closed source) to a more traditional closed-source model. This will not affect most users because the npm packages will remain publicly available, containing minified code. Only the availability of the source is changing.</p>
<p>See <a href="https://replicache.notion.site/Replicache-Licensing-Update-shared-external-fb3b66a69a2f4e84b22de56ac3e528b7" rel="nofollow">Replicache Licensing Update</a> for more information.</p>
<h1>šĀ Features</h1>
<ul>
<li>Introduce the concept of a <em>Release Build</em> and disable some expensive asserts in it (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1172259280" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/876" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/876/hovercard" href="https://github.com/rocicorp/replicache/issues/876">#876</a>)
<ul>
<li>You now need to make sure your build tools substitutes <code>process.env.NODE_ENV</code> to <code>"production"</code></li>
</ul>
</li>
<li>Expose the <em>profileID</em> used for licensing on <code>Replicache</code> and in push/pull requests (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1134435286" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/838" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/838/hovercard" href="https://github.com/rocicorp/replicache/issues/838">#838</a>)</li>
<li>Export <code>makeIDBName</code> as a convenience (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1174414340" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/883" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/883/hovercard" href="https://github.com/rocicorp/replicache/issues/883">#883</a>)</li>
<li><em>New Phone, Who Dis?</em> ā Graceful recovery when server doesnāt recognize client (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="841229717" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/335" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/335/hovercard" href="https://github.com/rocicorp/replicache/issues/335">#335</a>)</li>
<li>Enable custom log handling by adding <code>logSinks</code> to [<a href="https://doc.replicache.dev/api/interfaces/ReplicacheOptions#logsinks" rel="nofollow">ReplicacheOptions</a>]</li>
<li>Export <code>makeScanResult</code> ā a way to more easily implement <code>scan()</code> server-side (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1022281633" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/607" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/607/hovercard" href="https://github.com/rocicorp/replicache/issues/607">#607</a>)</li>
<li>Export watch as <code>experimentalWatch</code> ā allowing you to only be notified about the exact keys that changed. (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1136491643" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/839" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/839/hovercard" href="https://github.com/rocicorp/replicache/issues/839">#839</a>)</li>
<li>Export <code>version</code> const containing Replicache version number (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1223843200" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/991" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/991/hovercard" href="https://github.com/rocicorp/replicache/issues/991">#991</a>)</li>
</ul>
<h1>š§°Ā Fixes</h1>
<ul>
<li>Send errors from subscribe functions to <code>console.log</code> if no <code>onError</code> specified (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1163402992" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/862" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/862/hovercard" href="https://github.com/rocicorp/replicache/issues/862">#862</a>)</li>
<li>Recover gracefully from case where a tab gets backgrounded for a long time (weeks), gets frozen, and thus its Replicache state gets GCād. (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1105593894" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/784" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/784/hovercard" href="https://github.com/rocicorp/replicache/issues/784">#784</a>)</li>
<li>Fix spurious subscription re-fire in edge case (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1137373640" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/841" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/841/hovercard" href="https://github.com/rocicorp/replicache/issues/841">#841</a>)</li>
<li>Prevent concurrent pulls and persists. This was causing errors in the console such as "Wrong Sync Head". These errors were harmless, but annoying.</li>
</ul>
<h1><g-emoji class="g-emoji" alias="warning">ā ļø</g-emoji>Ā Breaking Changes</h1>
<ul>
<li>The <code>licenseKey</code> parameter to the <code>Replicache</code> constructor is now required. See <a href="https://doc.replicache.dev/licensing" rel="nofollow">Licensing Docs</a> for more information.</li>
<li>Removed top-level <code>scan</code>, <code>has</code>, <code>isEmpty</code>, <code>get</code> methods from <code>Replicache</code>. These have been deprecates since v8. Please use <code>Replicache.query()</code> instead. (#878729)</li>
<li>The entries returned from <code>scan().entries()</code> are now readonly tuples.</li>
<li>We now ship code with <code>process.env.NODE_ENV</code> in it. This does not work in a browser out of the box. You need to either define that or ensure your build tools (<a href="https://esbuild.github.io/api/#define" rel="nofollow">esbuild</a>, <a href="https://www.npmjs.com/package/rollup-plugin-inject-process-env" rel="nofollow">rollup</a>, <a href="https://webpack.js.org/guides/production/#specify-the-mode" rel="nofollow">webpack</a>, <a href="https://en.parceljs.org/env.html#%F0%9F%8C%B3-environment-variables" rel="nofollow">parcel</a>) does the correct substitution. (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1172259280" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/876" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/876/hovercard" href="https://github.com/rocicorp/replicache/issues/876">#876</a>)</li>
<li><a href="https://doc.replicache.dev/api/interfaces/AsyncIterableIteratorToArray" rel="nofollow"><code>AsyncIterableIteratorToArray</code></a> is now an interface not a class. This was causing problems with reusing Replicache on the server.</li>
</ul>
<h1>šĀ Performance</h1>
<ul>
<li>Scan speed improved about 79% (from ~350 MB/s to ~625 MB/s on our benchmark) in the new release build.</li>
</ul>aboodmantag:github.com,2008:Repository/267187299/v10.0.0-beta.02022-04-20T02:06:24Zv10.0.0-beta.0<p>Bump version to 10.0.0-beta.0.</p>aboodmantag:github.com,2008:Repository/267187299/v10.0.0-alpha.42022-04-13T13:11:36Zv10.0.0-alpha.4<p>Bump version to 10.0.0-alpha.4.</p>arvtag:github.com,2008:Repository/267187299/v10.0.0-alpha.32022-04-12T09:28:11Zv10.0.0-alpha.3<p>Bump version to 10.0.0-alpha.3.</p>aboodmantag:github.com,2008:Repository/267187299/v10.0.0-alpha.22022-04-08T19:07:36Zv10.0.0-alpha.2<p>Bump version to 10.0.0-alpha.2.</p>grgbkrtag:github.com,2008:Repository/267187299/v10.0.0-alpha.12022-04-07T22:46:56Zv10.0.0-alpha.1<p>Bump version to 10.0.0-alpha.1.</p>grgbkrtag:github.com,2008:Repository/267187299/v10.0.0-alpha.02022-04-06T00:48:06Zv10.0.0-alpha.0<p>Bump version to 10.0.0-alpha.0 in VERSION and BSL.txt. (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1193874922" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/917" data-hovercard-type="pull_request" data-hovercard-url="/rocicorp/replicache/pull/917/hovercard" href="https://github.com/rocicorp/replicache/pull/917">#917</a>)</p>grgbkrtag:github.com,2008:Repository/267187299/v9.0.02022-05-09T10:04:03Zv9.0.0: Realtime Storage<h1>Summary</h1>
<p>Replicache v9 has a rewritten storage system we call <em>Realtime Storage</em> which is must faster than the previous implementation.</p>
<p>For example, the median time to write a Replicache mutation that updates five dependent subscriptions is now ~3ms with up to 64MB of local storage on common hardware.</p>
<p>This performance allows developers to build highly responsive user interfaces that react instantaneously to input.</p>
<p>See the Realtime Storage and Performance sections below for more details.</p>
<blockquote>
<p>š” <strong>Note</strong><br>
These release notes document changes in Replicache between <a href="https://github.com/rocicorp/replicache/releases/tag/v8.0.3">v8.0.3</a> - the last stable release - and v9. They are largely duplicative of the v9.0.0-beta.* notes.</p>
</blockquote>
<h3>š Other Features</h3>
<ul>
<li>Replicache is faster, often dramatically so, on every benchmark as compared to v8 (see Performance below).</li>
<li>Replicache now has an <a href="https://doc.replicache.dev/api/#poke" rel="nofollow">experimental new <em>poke</em> method</a>. This enables directly programmatically adding data to Replicache without having to go through <em>pull</em>.</li>
<li>The mutation type sent to <code>replicache-push</code> now includes a <code>timestamp</code> property, which is the original (client-local) timestamp the mutation occurred at.</li>
<li>The size of <code>replicache.min.mjs.br</code> was reduced 28%, down to ~18kb.</li>
</ul>
<h3>š§° Fixes</h3>
<ul>
<li>Replicache is no longer slow when dev tools is open (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1037898673" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/634" data-hovercard-type="issue" data-hovercard-url="/rocicorp/replicache/issues/634/hovercard" href="https://github.com/rocicorp/replicache/issues/634">#634</a>)</li>
</ul>
<h3><g-emoji class="g-emoji" alias="warning">ā ļø</g-emoji> Breaking Changes</h3>
<ul>
<li>The <code>name</code> parameter is now required. This is used to differentiate Replicache data within the same origin. For security, provide a value that includes a unique ID for the current user. This ensures each user sees and modifies only their own local data. This has always been recommended but is now required. See "Multiple Users" below for more information.</li>
<li>The semantics of the <code>clientID</code> changed as compared to when <code>useMemstore</code> was <code>false</code> in v8. See Realtime Storage, below.</li>
<li>Removed the <code>pushAuth</code>, <code>getPushAuth</code>, <code>pullAuth</code>, and <code>getPullAuth</code> features. They were deprecated in Replicache 6.4.0 and have been replaced with <code>auth</code> and <code>getAuth</code>.</li>
<li>The <code>schemaVersion</code> property of the <code>Replicache</code> class is now read-only. This field was previously mutable, but setting it had no effect.</li>
</ul>
<h1>Realtime Storage</h1>
<p>In Replicache v8, there were two storage modes: <em>memory</em>, and <em>persistent</em>, controlled by the <code>useMemstore</code> constructor flag.</p>
<p>In persistent mode (<code>useMemstore=false</code>), each browser profile was a Replicache <em>client</em>, with a single <code>clientID</code> and storage area shared amongst all tabs over the lifetime of the profile. Accessing data directly from IDB is super slow ā way too slow to back interactive experiences like mouse movement and typing ā which forced developers to cache this data in memory on top of Replicache. This in turn created complexities keeping the in-memory and persistent state in sync. Additionally sharing a single storage area among many tabs created complexities versioning this storage ā you canāt change the schema of storage that other tabs are using!</p>
<p>In contrast, in memory mode (<code>useMemstore=true</code>), each unique instance of the <code>Replicache</code> class was its own client, with its own unique <code>clientID</code> and in-memory storage that only lasted the lifetime of that instance (usually a single page load). Being in memory, this mode was much faster and could back mouse movement and keystrokes, but was only suitable for small amounts of data since you wouldnāt want to re-download tons of data on every startup!</p>
<p>Starting in Replicache v9, <code>useMemstore</code> goes away and there is only one unified storage model that <em>mostly</em> combines the best attributes of the old memory mode and persistent mode: itās as fast (actually faster in most cases ā see Performance) than the old memory mode, but also persists every few seconds to storage so that data can be reused across instances.</p>
<p>Just like the old memory model, every instance of the <code>Replicache</code> class (again, every individual page load) is its own unique <em>client</em> with its own unique <code>clientID</code>. And <em>conceptually</em> each such client has its own distinct storage area, separate from all other clients.</p>
<blockquote>
<p>š” <strong>Note</strong><br>
Internally, we heavily deduplicate storage amongst clients, so that in reality each client only stores what is unique to it.</p>
</blockquote>
<p>When a new client is instantiated, Replicache <em>forks</em> the storage from some previous instance with the same <code>name</code> and <code>schemaVersion</code> (see schema versioning, below), so that the net effect is almost as if the storage was shared between the two tabs.</p>
<p>Importantly, though, changes in one tab do <em>not</em> show up immediately in other tabs because they donāt completely share storage. When online, it will appear as if storage is shared because changes in one tab will be synced rapidly to other tabs via the server. But when offline, that syncing will stop occurring and the tabs will proceed independently (see offline, below).</p>
<h2>Versioning</h2>
<p>A previous headache in persistent mode was versioning the local schema. We could not use the common strategy of migrating the schema on startup since other tabs might be using the storage at that moment. Also, writing migration code is difficult to do correctly and not a task our users reported being excited about.</p>
<p>With each client having its own logical storage, things are far simpler:</p>
<ul>
<li>When you construct Replicache, optionally provide a <code>schemaVersion</code> which is the version of the data understood by the calling application code.</li>
<li>When you change the format of the client view in a backward incompatible way, change the schema version.</li>
<li>When Replicache forks to create a new storage area, it only forks from previous clients with the same <code>schemaVersion</code> . This does mean that when you change your schema version, clients will have to download a new copy of the data. But this is much more robust than trying to migrate data, and we think itās the right tradeoff for almost all apps.</li>
<li>Other clients that havenāt yet upgraded proceed happily using the old schema in their own storage until they decide to upgrade.</li>
<li>Replicache also includes the <code>schemaVersion</code> in <code>replicache-push</code> and <code>replicache-pull</code> so that the server can respond appropriately.</li>
</ul>
<h2>Offline Support</h2>
<p>In the old persistent model, Replicacheās offline features were simple to understand: all the data was stored locally first in one profile-wide storage area, then synced to the server. Thus, Replicache apps would transition perfectly well between online and offline, tabs would appear to sync with each other while offline, and apps could even start up offline (provided developers used e.g., ServiceWorker properly to enable that).</p>
<p>Part of the tradeoff for getting faster performance is that Replicacheās offline-support is no longer quite as simple or robust.</p>
<p>Specifically:</p>
<ul>
<li>As with v8, a Replicache tab that is running online can go offline and continue working smoothly for some time (~hours to days depending on frequency of writes).</li>
<li>As with v8, Replicache saves changes locally every few seconds. Offline tabs can be switched away from or closed, and the computer can even shut down or crash without changes being lost. Any work done offline will be pushed to the server the next time the app is online using Replicacheās normal conflict resolution. For more information on how this works see <a href="https://github.com/rocicorp/replicache/releases/tag/v9.0.0-beta.1">"Mutation Recovery" in the v9.0.0-beta.1 Release Notes</a>.</li>
<li>Unlike v8, when offline, tabs <em>do not sync with each other</em>. Each proceeds independently until the network is restored. Note that this also means that if a tab is closed offline, then a new tab opened offline, the new tab will <em>not</em> see the changes from the first tab until the network is restored.</li>
</ul>
<p>We call this concept <em>Local Acceleration</em>, as opposed to <em>Offline-First</em>. In practice most modern web applications are not intended to be used for long periods offline, and canāt startup offline anyway. Local Acceleration captures the key benefits of offline-first for most applications ā instant responsiveness and resilience against short periods of network loss ā while optimizing for optimal online performance.</p>
<h1>Multiple Users</h1>
<p>Because Replicache reuses data persistently across tab sessions, itās always been important to properly namespace data by user. If a single browser profile is shared by multiple users, or if a single user uses multiple user accounts within the same application, we would not want to read or modify data from account A when account B logs into the app.</p>
<p>Replicache provides the <code>name</code> constructor option for this purpose: Each named Replicache instance within an origin has its own separate namespace. Previously in Replicache <code>name</code> was optional, but given its security importance we started making it required in v9.</p>
<blockquote>
<p><g-emoji class="g-emoji" alias="warning">ā ļø</g-emoji> <strong>Warning</strong><br>
Always provide a value for the <code>name</code> parameter that includes a unique user ID. This way each user will view and modify only their own data.</p>
</blockquote>
<h1>Compatibility</h1>
<p>v9 will upgrade cleanly from earlier Replicache versions, including v9 betas.</p>
<p>However, it does not migrate any unsent mutations across versions. For example, if the user goes offline in v8, makes a change, then comes back to the app online and the app includes v9, the mutations made while offline in v8 will be lost. We will begin migrating such mutations across major versions beginning in our first General Availability Release, which we plan for v10.</p>
<h1>Transitioning to v9</h1>
<p>Despite the above lengthy notes, the transition to v9 should be fairly seamless. Basically:</p>
<ul>
<li>Remove <code>useMemstore</code> from your <code>Replicache</code> constructor if present.</li>
<li>Ensure you provide a <code>name</code> parameter to <code>Replicache</code>, this is now required (generally the userID that is logged in).</li>
<li>Do not use the <code>clientID</code> as a parameter to generate the diff for <code>replicache-pull</code> from. Only the <code>cookie</code> should be used. This is because when Replicache forks to create a new client, it assigns a new clientID. If you are using the <code>clientID</code> as an input to <code>replicache-pull</code> you will find that in many cases the <code>clientID</code> is new and thus probably send reset patches to every new client.</li>
</ul>
<h1>Performance</h1>
<table>
<thead>
<tr>
<th>Metric</th>
<th>v9</th>
<th>v8 (persistent)</th>
<th>v8 (mem)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Write/Sub/Read (1mb total storage)</td>
<td>2.8ms</td>
<td>72ms (+45x)</td>
<td>2.8ms (+0.0x)</td>
</tr>
<tr>
<td>Write/Sub/Read (16mb total storage)</td>
<td>3.2ms</td>
<td>267ms (+83x)</td>
<td>5.4ms (+1.7x)</td>
</tr>
<tr>
<td>Bulk Populate 1mb</td>
<td>45ms</td>
<td>183ms (+4x)</td>
<td>108ms (+2.4x)</td>
</tr>
<tr>
<td>Scan 1mb</td>
<td>3.1ms</td>
<td>77ms (+25x)</td>
<td>3.7ms (+1.2x)</td>
</tr>
<tr>
<td>Create Index (5mb total storage)</td>
<td>240ms</td>
<td>1150ms (+4.8x)</td>
<td>300ms (+1.25x)</td>
</tr>
</tbody>
</table>aboodmantag:github.com,2008:Repository/267187299/v9.0.0-beta.22022-02-25T01:16:49Zv9.0.0-beta.2: HMR Fix<h1>Summary</h1>
<p>See the <a href="https://github.com/rocicorp/replicache/releases/tag/v9.0.0-beta.0">v9.0.0-beta.0</a> and <a href="https://github.com/rocicorp/replicache/releases/tag/v9.0.0-beta.1">v9.0.0-beta.1</a> Release Notes first if you are upgrading from v8. Additionally:</p>
<h3>š Features</h3>
<ul>
<li>We now prefix Replicache IDB instances with the string <code>rep:</code> so they can be easily distinguished in developer tools (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1137388037" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/842" data-hovercard-type="pull_request" data-hovercard-url="/rocicorp/replicache/pull/842/hovercard" href="https://github.com/rocicorp/replicache/pull/842">#842</a>)</li>
</ul>
<h3>š§° Fixes</h3>
<ul>
<li>Fix bug that was preventing Hot Module Replacement from working (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1149601404" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/846" data-hovercard-type="pull_request" data-hovercard-url="/rocicorp/replicache/pull/846/hovercard" href="https://github.com/rocicorp/replicache/pull/846">#846</a>)</li>
<li>Remove reference to <code>window</code> that was preventing Replicache from working within web workers (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1138414605" data-permission-text="Title is private" data-url="https://github.com/rocicorp/replicache/issues/844" data-hovercard-type="pull_request" data-hovercard-url="/rocicorp/replicache/pull/844/hovercard" href="https://github.com/rocicorp/replicache/pull/844">#844</a>)</li>
</ul>
<h1>Compatibility</h1>
<p>v9.0.0-beta.2 will upgrade cleanly from 9.0.0-beta.1 or earlier Replicache versions.</p>
<p>However, it does not migrate any unsent mutations across versions. For example, if the user goes offline in v8 or v9.0.0-beta.1, makes a change, then comes back to the app online and the app includes v9, the mutations made while offline in v8 will be lost. We will begin migrating such mutations across major versions beginning in our first General Availability Release, which we plan for v10.</p>aboodmantag:github.com,2008:Repository/267187299/v9.0.0-beta.12022-02-11T08:08:29Zv9.0.0-beta.1: Mutation Recovery<h1>Summary</h1>
<p>See the <a href="https://github.com/rocicorp/replicache/releases/tag/v9.0.0-beta.0">v9.0.0-beta.0 Release Notes</a> first if you are upgrading from v8. Additionally:</p>
<h3>šĀ Features</h3>
<ul>
<li>Changes made while a tab is offline are now guaranteed to be sent next time Replicache connects (see Mutation Recovery below).</li>
</ul>
<h3><g-emoji class="g-emoji" alias="warning">ā ļø</g-emoji>Ā Breaking Changes</h3>
<ul>
<li>Removed the deprecated <code>pushAuth</code>, <code>getPushAuth</code>, <code>pullAuth</code>, and <code>getPullAuth</code> features. These features were deprecated in Replicache 6.4.0 and have been replaced with <code>auth</code> and <code>getAuth</code>.</li>
<li>The <code>schemaVersion</code> property of the <code>Replicache</code> class is now read-only. This field was previously mutable, but setting it had no effect.</li>
</ul>
<h1>Mutation Recovery</h1>
<p>The major change in 9.0.0-beta.1 over the previous 9.0.0-beta.0 is the addition of <em>Mutation Recovery</em>.</p>
<p>In 9.0.0-beta.0, if a tab was offline and then closed (or crashed, froze, etc) before going back online, any mutations made in that tab would be permanently lost. In the release notes for 9.0.0-beta.0, we noted this was temporary and would be fixed in the next beta. Mutation Recovery implements the fix.</p>
<p>It works as follows:</p>
<ul>
<li>While a Replicache instance is running, it periodically syncs with the server and stores pending mutations locally.</li>
<li>Each time Replicache syncs with the server, any mutations acknowledged by the server are removed from local storage.</li>
<li>If a Replicache instance is offline, pending mutations accumulate until it comes back online.</li>
<li>If the Replicache instance is closed before it goes back online, then prior to Mutation Recovery those pending mutations would never be sent.</li>
<li><em>With</em> Mutation Recovery, when each new Replicache instance is constructed, it first checks to see if any other instance (having the same <code>name</code>, see below) has pending mutations that need to be sent. If such pending mutations are found then the running instance <em>recovers</em> those mutations and pushes them to the server. We also run this recovery process when we detect that connection to the server has moved from offline to online.</li>
<li>Mutation Recovery works whether the source tab crashes, gets <a href="https://developers.google.com/web/updates/2018/07/page-lifecycle-api#state-frozen" rel="nofollow">frozen</a>, gets put in the <a href="https://web.dev/bfcache/" rel="nofollow">bfcache</a>, gets <a href="https://blog.chromium.org/2020/11/tab-throttling-and-more-performance.html" rel="nofollow">throttled</a>, or even if the source tab is still running but simply hasnāt pushed for some unknown reason. The process actually doesnāt care about the state of the source tab at all: each new instance simply checks every other instance and sends any pending mutations found.</li>
</ul>
<h1>Multiple Users</h1>
<p>Because Replicache reuses data persistently across tab sessions, itās always been important to properly namespace data by user. If a single browser profile is shared by multiple users, or if a single user uses multiple user accounts within the same application, we would not want to read or modify data from account A when account B logs into the app.</p>
<p>Replicache has always provided the <code>name</code> constructor option for this purpose: Each named Replicache instance within an origin has its own separate namespace.</p>
<p>Mutation Recovery reuses the same mechanism. When one Replicache instance looks for mutations to recover from other instances, it only considers instances with the same <code>name</code>.</p>
<blockquote>
<p><g-emoji class="g-emoji" alias="warning">ā ļø</g-emoji> <strong>Warning</strong><br>
Always provide a value for the <code>name</code> parameter that includes a unique user ID. This way each user will view and modify only their own data.</p>
</blockquote>
<h1>Compatibility</h1>
<p>v9.0.0-beta.1 will upgrade cleanly from 9.0.0-beta.0 or earlier Replicache versions.</p>
<p>However, it does not migrate any unsent mutations across versions. For example, if the user goes offline in v8, makes a change, then comes back to the app online and the app includes v9, the mutations made while offline in v8 will be lost. We will begin migrating such mutations across major versions beginning in our first General Availability Release, which we plan for v10.</p>aboodman