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

# Release Notes

> Explore release notes across every Ditto product.

export function ReleaseNotesPager() {
  const currentPage = () => {
    const m = window.location.pathname.match(/\/page-(\d+)$/);
    return m ? Number(m[1]) : 1;
  };
  const base = () => window.location.pathname.replace(/\/page-\d+$/, "");
  const target = pageNum => (pageNum === 1 ? base() : base() + "/page-" + pageNum) + window.location.search;
  const [total, setTotal] = useState(null);
  useEffect(() => {
    const el = document.querySelector("[data-release-notes-filters]");
    const n = el ? Number(el.getAttribute("data-rn-total-pages")) : NaN;
    if (Number.isFinite(n) && n >= 1) setTotal(n);
  }, []);
  if (!total || total <= 1) return null;
  const cur = currentPage();
  const hasNewer = cur > 1;
  const hasOlder = cur < total;
  const propsFor = (pageNum, rel) => ({
    rel,
    href: target(pageNum),
    onMouseEnter: e => {
      e.currentTarget.href = target(pageNum);
    },
    onMouseDown: e => {
      e.currentTarget.href = target(pageNum);
    },
    onFocus: e => {
      e.currentTarget.href = target(pageNum);
    },
    onClick: e => {
      if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
      e.preventDefault();
      window.location.assign(target(pageNum));
    }
  });
  return <nav id="release-notes-pager" className="rnp rn-upd" aria-label="Release notes pages">
      <style>{`
        /* Bottom-of-stream pagination: belongs to the main content column
           (.rn-upd width), visually separated from the final announcement by
           spacing + a subtle top boundary (Mintlify-neutral conventions).
           The id + scroll-margin are the anchor contract for the TOC's
           "More releases ↓" jump link (Mintlify's own --scroll-mt keeps the
           landed position below the navbar); both are additive — the pager's
           appearance and behavior are otherwise unchanged. */
        .rnp { box-sizing: border-box; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: 48px; padding: 20px 0 8px; border-top: 1px solid rgba(23, 23, 23, 0.1); font-size: 14px; scroll-margin-top: var(--scroll-mt, 96px); }
        html.dark .rnp { border-top-color: rgba(255, 255, 255, 0.12); }
        .rnp-pos { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: #6b7280; }
        html.dark .rnp-pos { color: #9ca3af; }
        .rnp-link { display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; border-radius: 9999px; border: 1px solid rgba(23, 23, 23, 0.15); color: #374151; font-weight: 600; text-decoration: none; }
        .rnp-link:hover { border-color: #111827; color: #111827; }
        html.dark .rnp-link { border-color: rgba(255, 255, 255, 0.16); color: #d1d5db; }
        html.dark .rnp-link:hover { border-color: #e5e7eb; color: #e5e7eb; }
        .rnp-link:focus-visible { outline: 2px solid #688ae8; outline-offset: 2px; }
        @media (max-width: 560px) {
          .rnp { flex-direction: column; align-items: flex-start; }
        }
      `}</style>
      {hasNewer ? <a className="rnp-link" {...propsFor(cur - 1, "prev")}>← Newer releases</a> : <span className="rnp-pos">Page {cur} of {total}</span>}
      {hasNewer && hasOlder ? <span className="rnp-pos">Page {cur} of {total}</span> : null}
      {hasOlder ? <a className="rnp-link" {...propsFor(cur + 1, "next")}>Older releases →</a> : hasNewer ? <span className="rnp-pos">Page {cur} of {total}</span> : null}
    </nav>;
}

export function ReleaseNotesFilters({view, page, totalPages, tocEntries, rangeStart, rangeEnd, rangeTotal}) {
  const [open, setOpen] = useState(false);
  const controlRef = useRef(null);
  const basePath = window.location.pathname.replace(/\/page-\d+$/, "");
  const WRAPPER_PREFIX = "/sdk/latest/release-notes-hub/";
  const activeId = basePath === "/release-notes" ? "all" : basePath === "/release-notes/sdk" ? "sdk-all" : basePath === "/release-notes/common" ? "common" : basePath === "/release-notes/cloud" ? "cloud" : basePath.startsWith("/release-notes/sdk/") ? basePath.slice(("/release-notes/sdk/").length) : basePath.startsWith(WRAPPER_PREFIX) ? basePath.slice(WRAPPER_PREFIX.length) : basePath === "/cloud/release-notes-hub" ? "cloud" : "all";
  const tocSlug = label => label.toLowerCase().replace(/[(),]/g, "").replace(/[.\s]/g, "-");
  const TOC_GROUP_ORDER = ["SDK", "Cloud Platform"];
  const grouped = view === "all" || view === "sdk-all" ? TOC_GROUP_ORDER.map(g => ({
    group: g,
    entries: tocEntries.filter(e => e.group === g)
  })).filter(g => g.entries.length > 0) : [{
    group: null,
    entries: tocEntries
  }];
  const tocRow = entry => <li key={entry.label}>
      <a className="rnff-toc-link" href={"#" + tocSlug(entry.label)}>
        {entry.label}
      </a>
    </li>;
  const VIEW_HREF = {
    "all": "/release-notes",
    "sdk-all": "/release-notes/sdk",
    "common": "/release-notes/common",
    "cloud": "/release-notes/cloud"
  };
  const viewHref = id => VIEW_HREF[id] || `/release-notes/sdk/${id}`;
  const PLATFORM_LINKS = [["swift", "Swift"], ["kotlin", "Kotlin"], ["flutter", "Flutter"], ["react-native", "React Native"], ["javascript-web", "JavaScript (Web)"], ["javascript-nodejs", "Node.js"], ["java", "Java"], ["c-sharp", "C#"], ["cpp", "C++"], ["rust", "Rust"], ["go", "Go"]];
  const DEST_ICONS = {
    "all": ["clipboard-list", "solid"],
    "sdk-all": ["laptop-mobile", "solid"],
    "common": ["cubes-stacked", "solid"],
    "cloud": ["cloud", "regular"]
  };
  const PLATFORM_ICONS = {
    "swift": ["apple", "brands"],
    "kotlin": ["android", "brands"],
    "flutter": ["flutter", "brands"],
    "react-native": ["react", "brands"],
    "javascript-web": ["js", "brands"],
    "javascript-nodejs": ["js", "brands"],
    "java": ["java", "brands"],
    "c-sharp": ["microsoft", "brands"],
    "cpp": ["code", "solid"],
    "rust": ["rust", "brands"],
    "go": ["golang", "brands"]
  };
  useEffect(() => {
    if (!open) return;
    const onDown = e => {
      if (controlRef.current && !controlRef.current.contains(e.target)) setOpen(false);
    };
    const onFocus = e => {
      if (controlRef.current && !controlRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", onDown);
    document.addEventListener("focusin", onFocus);
    return () => {
      document.removeEventListener("mousedown", onDown);
      document.removeEventListener("focusin", onFocus);
    };
  }, [open]);
  const destLink = (id, label, icon) => <a className="rnff-dest" data-active={activeId === id ? "true" : undefined} href={viewHref(id)}>
      {icon && <span className="rnff-dest-icon">
          <Icon icon={icon[0]} iconType={icon[1]} />
        </span>}
      <span>{label}</span>
    </a>;
  return <div className="rnff-stick not-prose" data-release-notes-filters="" data-rn-total-pages={totalPages}>
      {}
      <style>{`
        /* RESPONSIVE BREAKOUT SYSTEM: card 290px, gap 36px; the rail's sticky
           top tracks Mintlify's NATIVE right-rail offset (--scroll-mt =
           navbar bottom + 40, banner-aware, maintained live by Mintlify's own
           scroll-margin script; 180px fallback until that script runs).
           Below 1260px: normal single-column flow. */
        :root {
          --rn-card-w: 290px;
          --rn-gap: 36px;
          --rn-off: min(max(calc(100vw - 1204px), 0px), 350px);
        }
        .rn-upd { width: min(calc(100% - var(--rn-card-w) - var(--rn-gap) + var(--rn-off)), 100%); }
        /* COPY PAGE = STANDARD-LAYOUT POSITION (stakeholder polish): on
           rail-active desktop viewports, Mintlify's page-context menu (Copy
           page) shifts left so its right edge aligns with the releases
           column's right edge — the same relationship standard docs pages
           have (button over the article column, right rail beside it). The
           margin mirrors the .rn-upd width formula (card + gap - off), so it
           stays correct at every width with no tuning of its own; max()
           clamps it to 0 where the releases column is full-width (~1530px+,
           the same point .rn-upd's min() caps). Gated to the rail-active
           conditions (min-width 1261, min-height 641) so the collapsed
           layouts below keep the native header placement. This stylesheet
           only loads on release-notes routes, so no other page's Copy Page
           button can be affected. */
        @media (min-width: 1261px) and (min-height: 641px) {
          #page-context-menu { margin-right: max(0px, calc(var(--rn-card-w) + var(--rn-gap) - var(--rn-off))); }
        }
        /* STICKY BOUNDARY (corrected): the wrapper's box height = the rail's
           real visual height formula, compensated by an equal negative top
           margin; the sticky containment rule then measures the rail's TRUE
           extent, so the rail stops at the end of the release-notes content
           region instead of floating into Mintlify's native prev/next +
           footer area. */
        .rnff-stick { box-sizing: border-box; overflow: visible; width: var(--rn-card-w); max-width: none; margin-left: auto; position: sticky; top: var(--scroll-mt, 180px); height: max(240px, calc(100vh - var(--scroll-mt, 180px) - 24px)); margin-top: min(-240px, calc(var(--scroll-mt, 180px) + 24px - 100vh)); margin-bottom: 0; transform: translateX(var(--rn-off)); }
        .rnff-card { border: 1px solid rgba(23, 23, 23, 0.1); border-radius: 16px; padding: 16px 20px; background: #ffffff; }
        html.dark .rnff-card { border-color: rgba(255, 255, 255, 0.12); background: #171717; }
        .rnff-label { font-family: Inter, -apple-system, system-ui, "Segoe UI", sans-serif; font-size: 14px; font-weight: 500; line-height: 24px; letter-spacing: normal; text-transform: none; color: #171717; margin: 0 0 4px; }
        html.dark .rnff-label { color: #dfdfdf; }
        .rnff-group + .rnff-group { margin-top: 16px; }
        /* Destination rows — typography measured from the existing LEFT
           sidebar (2026-09-16): nav item = 14px / 400 / 24px / normal case /
           #3f3f3f (dark #9f9f9f), font stack Inter/system; CURRENT item =
           same weight, darker color #1e1e1e. Section labels match the
           "Key Concepts" group header (14px / 500 / normal case). Rows keep
           the sidebar shape: full-width rectangular rows + icon gutter, NOT
           chips/pills. */
        .rnff-dest { display: flex; align-items: center; gap: 8px; padding: 3px 8px; margin: 0 -8px; font-family: Inter, -apple-system, system-ui, "Segoe UI", sans-serif; font-size: 14px; font-weight: 400; line-height: 24px; color: #3f3f3f; text-decoration: none; border-radius: 8px; }
        .rnff-dest:hover { color: #111827; background: rgba(23, 23, 23, 0.04); }
        html.dark .rnff-dest { color: #9f9f9f; }
        html.dark .rnff-dest:hover { color: #e5e7eb; background: rgba(255, 255, 255, 0.06); }
        .rnff-dest[data-active="true"] { font-weight: 400; color: #1e1e1e; background: rgba(23, 23, 23, 0.06); }
        html.dark .rnff-dest[data-active="true"] { color: #e5e5e5; background: rgba(255, 255, 255, 0.1); }
        .rnff-dest:focus-visible { outline: 2px solid #688ae8; outline-offset: 2px; }
        .rnff-dest-icon { display: inline-flex; width: 16px; flex: 0 0 16px; justify-content: center; color: inherit; opacity: 0.85; }
        .rnff-dest-icon svg { width: 14px; height: 14px; }
        /* Platform disclosure control — a field-shaped button that reveals
           the destination link list IN FLOW (no overlay, no overflow risk,
           no z-index games). Closed height matches the replaced select (~34px)
           so the vertical-space win from the dropdown change is retained. */
        .rnff-plat-toggle { display: flex; align-items: center; gap: 8px; width: 100%; height: 34px; padding: 0 10px; font-family: Inter, -apple-system, system-ui, "Segoe UI", sans-serif; font-size: 14px; font-weight: 400; line-height: 24px; text-align: left; color: #3f3f3f; background: #ffffff; border: 1px solid rgba(23, 23, 23, 0.15); border-radius: 8px; cursor: pointer; }
        html.dark .rnff-plat-toggle { background: #171717; color: #9f9f9f; border-color: rgba(255, 255, 255, 0.16); }
        .rnff-plat-toggle:hover { border-color: #111827; }
        html.dark .rnff-plat-toggle:hover { border-color: #e5e7eb; }
        .rnff-plat-toggle:focus-visible { outline: 2px solid #688ae8; outline-offset: 2px; }
        .rnff-plat-label { flex: 1 1 auto; }
        .rnff-plat-caret { display: inline-flex; color: #9ca3af; }
        .rnff-plat-caret svg { width: 12px; height: 12px; }
        /* OPEN MENU OVERLAYS the content below (incl. the TOC) like a normal
           dropdown/popover: absolute within .rnff-plat (position:relative),
           so opening never grows the card or pushes the TOC down. All 11
           options render at once — no max-height, no internal scroll.
           Clipping: no ancestor hides overflow (stick/rail/card are all
           overflow:visible), so absolute positioning is safe. */
        .rnff-plat { position: relative; }
        .rnff-plat-list { list-style: none; position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 50; margin: 0; padding: 4px 0; background: #ffffff; border: 1px solid rgba(23, 23, 23, 0.12); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); }
        html.dark .rnff-plat-list { background: #171717; border-color: rgba(255, 255, 255, 0.14); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); }
        /* Dropdown option spacing (manual-review polish): rows inside the
           menu get a roomier, consistent inset — icons sit 12px from the
           menu edge with a 12px icon→label gap (the site's 4px spacing
           scale), so all 11 icons share one column and all labels share one
           text column. Row heights and menu dimensions are unchanged. */
        .rnff-plat-list .rnff-dest { padding: 3px 12px; gap: 12px; margin: 0; }
        /* Uppercase platform labels inside the dropdown only (stakeholder
           presentation request — matches the site's Aeonik/uppercase brand
           usage for navigation accents). Route ids/labels/metadata are
           unchanged; this is a visual transform of the option text. */
        .rnff-plat-label, .rnff-plat-list .rnff-dest span:last-child { text-transform: uppercase; }
        @media (max-width: 1260px) {
          .rn-upd { width: 100%; }
          .rnff-stick { transform: none; width: 100%; height: auto; position: static; margin: 0 0 24px; }
        }
        /* Extremely SHORT viewports: same static collapse as narrow screens. */
        @media (max-height: 640px) and (min-width: 1261px) {
          .rn-upd { width: 100%; }
          .rnff-stick { transform: none; width: 100%; height: auto; position: static; margin: 0 0 24px; }
          .rnff-rail { max-height: none; }
        }
        /* RIGHT-RAIL AS ONE BOUNDED REGION (unchanged): flex column capped at
           the viewport height remaining under the sticky top offset; the
           destination card never shrinks; the TOC takes leftover space and
           scrolls independently. */
        .rnff-rail { display: flex; flex-direction: column; max-height: max(240px, calc(100vh - var(--scroll-mt, 180px) - 24px)); }
        .rnff-card { flex: 0 0 auto; }
        .rnff-toc { flex: 1 1 auto; min-height: 0; margin-top: 20px; padding: 10px 12px; border: 1px solid rgba(23, 23, 23, 0.08); border-radius: 12px; overflow-y: auto; overscroll-behavior: contain; }
        html.dark .rnff-toc { border-color: rgba(255, 255, 255, 0.1); }
        /* TOC: entries match the site's NATIVE right-rail TOC convention
           (styles.css table-of-contents rule: Aeonik Fono + uppercase;
           measured native entries: 14px / 400 / 24px, header 14px / 500).
           NOTE: no backticks inside this <style> template literal — a
           backtick terminates the template and silently kills the whole
           component's export (measured the hard way). */
        .rnff-toc-label { font-family: Inter, -apple-system, system-ui, "Segoe UI", sans-serif; font-size: 14px; font-weight: 500; line-height: 24px; letter-spacing: normal; text-transform: none; color: #171717; margin: 0 0 4px; }
        html.dark .rnff-toc-label { color: #dfdfdf; }
        /* TOC header row: label left, announcement range right (same row,
           visually subordinate — 12px grey, the group-label's muted tones).
           Range values arrive as generated route props (registry-derived);
           the component never computes them. */
        .rnff-toc-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
        .rnff-toc-range { font-family: 'Aeonik Fono', monospace; font-size: 12px; font-weight: 400; line-height: 24px; letter-spacing: normal; text-transform: none; color: #9ca3af; }
        html.dark .rnff-toc-range { color: #6b7280; }
        /* "More releases ↓" — TOC-footer jump link to the existing bottom
           pager (#release-notes-pager). Additive navigation only: rendered
           solely when the generated route says the view is paginated
           (totalPages > 1), so it never points at an unmounted pager. */
        .rnff-toc-more { margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(23, 23, 23, 0.08); }
        html.dark .rnff-toc-more { border-top-color: rgba(255, 255, 255, 0.1); }
        .rnff-toc-group-label { font-family: 'Aeonik Fono', monospace; font-size: 12px; font-weight: 500; letter-spacing: normal; text-transform: uppercase; color: #9ca3af; margin: 12px 0 4px; }
        html.dark .rnff-toc-group-label { color: #6b7280; }
        .rnff-toc ul { list-style: none; margin: 0; padding: 0; }
        .rnff-toc li { margin: 0; }
        .rnff-toc-link { display: block; padding: 3px 0; font-family: 'Aeonik Fono', monospace; font-size: 14px; font-weight: 400; line-height: 24px; letter-spacing: normal; text-transform: uppercase; color: #707070; text-decoration: none; }
        .rnff-toc-link:hover { color: #1e1e1e; text-decoration: underline; }
        html.dark .rnff-toc-link { color: #9f9f9f; }
        html.dark .rnff-toc-link:hover { color: #e5e5e5; }
        .rnff-toc a:focus-visible { outline: 2px solid #688ae8; outline-offset: 2px; border-radius: 4px; }
        @media (max-width: 1260px) {
          .rnff-toc { display: none; }
        }
      `}</style>
      <div className="rnff-rail">
      <div className="rnff-card">
      <div role="group" aria-label="Release Notes" className="rnff-group">
        <p className="rnff-label">Release Notes</p>
        <nav aria-label="Release notes destinations">
          {destLink("all", "All", DEST_ICONS["all"])}
          {destLink("sdk-all", "SDK - All", DEST_ICONS["sdk-all"])}
          {destLink("common", "SDK - Common", DEST_ICONS["common"])}
          {destLink("cloud", "Cloud Platform", DEST_ICONS["cloud"])}
        </nav>
      </div>

      <div role="group" aria-label="SDK Platforms" className="rnff-group">
        <p className="rnff-label">SDK Platforms</p>
        {}
        {(() => {
    const activeIsPlatform = !!PLATFORM_ICONS[activeId];
    const activeLabel = activeIsPlatform ? PLATFORM_LINKS.find(([s]) => s === activeId)?.[1] : null;
    return <div className="rnff-plat" ref={controlRef}>
              <button type="button" className="rnff-plat-toggle" aria-expanded={open ? "true" : "false"} aria-controls="rn-platform-destinations" onClick={() => setOpen(!open)} onKeyDown={e => {
      if (e.key === "ArrowDown" && !open) {
        e.preventDefault();
        setOpen(true);
      }
      if (e.key === "Escape" && open) {
        e.preventDefault();
        setOpen(false);
      }
    }}>
                {activeIsPlatform && <span className="rnff-dest-icon">
                    <Icon icon={PLATFORM_ICONS[activeId][0]} iconType={PLATFORM_ICONS[activeId][1]} />
                  </span>}
                <span className="rnff-plat-label">
                  {activeLabel || "Select a platform…"}
                </span>
                <span className="rnff-plat-caret" aria-hidden="true">
                  <Icon icon={open ? "chevron-up" : "chevron-down"} iconType="solid" />
                </span>
              </button>
              {open && <ul id="rn-platform-destinations" className="rnff-plat-list" aria-label="SDK platform destinations">
                  {PLATFORM_LINKS.map(([slug, label]) => <li key={slug}>
                      <a className="rnff-dest" data-active={activeId === slug ? "true" : undefined} href={viewHref(slug)} onKeyDown={e => {
      const links = [...controlRef.current.querySelectorAll(".rnff-plat-list a")];
      const i = links.indexOf(e.currentTarget);
      if (e.key === "ArrowDown") {
        e.preventDefault();
        (links[i + 1] || links[0]).focus();
      }
      if (e.key === "ArrowUp") {
        e.preventDefault();
        (links[i - 1] || links[links.length - 1]).focus();
      }
      if (e.key === "Escape") {
        e.preventDefault();
        setOpen(false);
        controlRef.current.querySelector(".rnff-plat-toggle").focus();
      }
    }}>
                        <span className="rnff-dest-icon">
                          <Icon icon={PLATFORM_ICONS[slug][0]} iconType={PLATFORM_ICONS[slug][1]} />
                        </span>
                        <span>{label}</span>
                      </a>
                    </li>)}
                </ul>}
            </div>;
  })()}
      </div>
      </div>
      <nav className="rnff-toc" aria-label="Release notes table of contents">
        <div className="rnff-toc-head">
          <p className="rnff-toc-label">Table of Contents</p>
          {rangeTotal > 0 && <span className="rnff-toc-range">{rangeStart}–{rangeEnd} of {rangeTotal}</span>}
        </div>
        {grouped.map(g => <div key={g.group || "flat"}>
            {g.group && <p className="rnff-toc-group-label">{g.group}</p>}
            <ul>
              {g.entries.map(entry => tocRow(entry))}
            </ul>
          </div>)}
        {totalPages > 1 && <a className="rnff-toc-link rnff-toc-more" href="#release-notes-pager">More releases ↓</a>}
      </nav>
    </div>
    </div>;
}

<ReleaseNotesFilters view="cloud" page={1} totalPages={1} rangeStart={1} rangeEnd={6} rangeTotal={6} tocEntries={[{"label":"v1.65.1","group":"Cloud Platform"},{"label":"v1.65.0","group":"Cloud Platform"},{"label":"v1.64.4","group":"Cloud Platform"},{"label":"v1.64.3","group":"Cloud Platform"},{"label":"v1.64.2","group":"Cloud Platform"},{"label":"v1.64.1","group":"Cloud Platform"}]} />

<Update label="v1.65.1" description="Release Date: w/c Aug 24, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.65.1 is a patch release that adds optional sharding of CDC output across multiple Kafka producers to raise produce throughput, and fixes a webhook dispatcher failure that could stop webhooks being delivered after a Kafka reconnect.**

  <Icon icon="plus" iconType="solid" horizontal /> **Added:**

  * CDC can shard its output across multiple idempotent Kafka producers, controlled by the new `PRODUCER_SHARDS` setting, raising produce throughput to downstream consumers under sustained write load. The default of `1` leaves behavior unchanged

  <Note>
    This does not change CDC's ordering contract. Changes for an individual document are still delivered sequentially, and global ordering across documents is not guaranteed either way - see [Event Ordering](/cloud/cdc#event-ordering). Contact Ditto before raising `PRODUCER_SHARDS` above `1`, as it has a deployment prerequisite.
  </Note>

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:**

  * The webhook dispatcher no longer aborts when its Kafka consumer reconnects, so a broker restart or partition rebalance no longer leaves it restarting repeatedly instead of delivering webhooks
</Update>

<Update label="v1.65.0" description="Release Date: w/c Jul 27, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.65.0 is a minor release with a broad set of DQL enhancements. It adds new scalar functions, request profiling, and execution-time limits. It also brings significant memory reductions for query results and store observers, plus a range of reliability and safety fixes across sync, DQL, and the HTTP API.**

  <Icon icon="plus" iconType="solid" horizontal /> **Added:**

  * A new `EXECUTE FUNCTION` DQL statement for running DQL functions with side effects in a controlled environment
  * Additional DQL scalar functions, including common trigonometric functions and further array-processing functions
  * An optional DQL parameter that limits a request's execution time, stopping requests that exceed the limit and completing them with an error
  * Automatic diagnostic logging for long-running DQL requests, controlled by the new `DQL_SLOW_REQUEST_WARN_SECONDS` system parameter
  * Two new [`request_history` virtual collection](/dql/virtual-collections#request-history) qualifiers: one that captures requests carrying profiling information (the `PROFILE` keyword or `#profile` directive) when set to `TRUE`, and one that captures requests by `requestType`
  * A new `transports_websocket_watchdog_interval_secs` system parameter for tuning the WebSocket client watchdog interval
  * A guard that halts a node rather than applying a change produced by a newer, unsupported release, preventing silent, permanent divergence if a node is rolled back to an older release after the rest of the cluster has upgraded
  * A new metric that measures Ditto auth time separately from customer webhook time

  <Note>
    This guard does not change behavior on its own. It establishes **1.65.0 as a minimum baseline**: future releases may require every node in a cluster to be running 1.65.0 or higher before upgrading, so that this protection is already in place.
  </Note>

  <Icon icon="arrows-rotate" iconType="solid" horizontal /> **Changed:**

  * Oversized documents written through the HTTP API now return `413` with a message explaining the document is too large (v4 `store/write` upsert and v5 `store/execute`); the v4 update result reports them in a new `documentTooLarge` count, instead of a misleading 500/503 or a silent success
  * Query plan specialisation for `COUNT(*)` queries now applies when there are top-level field `IS NULL` predicates
  * Structured peer ID fields now render resolvable peer-key prefixes instead of legacy suffixes; field names are unchanged

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:**

  * DQL queries with long `AND`/`OR` operator chains no longer cause a Subscription Server panic from exceeding parser recursion limits
  * Invalid TLS identity and certificate configuration now returns actionable errors instead of being silently ignored or panicking
  * The DQL `object_content` scalar function now correctly processes the `"nesting"` configuration value `"only"` when passed as part of an object
  * The DQL `substr` negative index calculation and the `lpad` and `rpad` scalar functions now handle multi-byte characters correctly

  <Icon icon="rocket" iconType="solid" horizontal /> **Performance:**

  * DQL query results are held in a compact form and expanded only when read, reducing the memory retained by query results and store observers, especially for large result sets
  * DQL store observers no longer keep observed documents fully decoded between updates, and observers whose query cannot reuse the previous result incrementally (for example projections or index-backed lookups) no longer retain a copy of the previous result set between updates
  * Reading a document — including the documents a store observer delivers on each update — no longer pins its decoded form in memory, reducing the memory retained by long-lived observers
</Update>

<Update label="v1.64.4" description="Release Date: w/c Jul 13, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.64.4 is a small patch release that adds an opt-in transaction-log apply pipeline for higher sustained apply throughput.**

  <Icon icon="rocket" iconType="solid" horizontal /> **Performance:**

  * An opt-in transaction-log apply pipeline that overlaps polling and deserialization with apply, and batches remote multi-write dispatch, raising sustained apply throughput. Enabled with the `TXLOG_PIPELINE_ENABLED` setting; when it is unset the store runs the previous behavior
</Update>

<Update label="v1.64.3" description="Release Date: w/c Jun 22, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.64.3 is a small patch release that optimises CDC performance.**

  <Icon icon="rocket" iconType="solid" horizontal /> **Performance:**

  * CDC optimised to improve throughput to downstream consumers under sustained write load
</Update>

<Update label="v1.64.2" description="Release Date: w/c Jun 22, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.64.2 is a small patch release that bounds how far Change Data Capture is allowed to fall behind, protecting store storage growth when a CDC consumer lags.**

  <Icon icon="plus" iconType="solid" horizontal /> **Added:**

  * A bound on how far behind a Change Data Capture consumer may fall, configured with the new `MAX_SESSION_VERSION_LAG` setting. A consumer that lags without a bound holds back store cleanup and lets storage grow; with a bound in place the store stops holding data back past the configured lag. Leaving it unset keeps the previous unbounded behavior
</Update>

<Update label="v1.64.1" description="Release Date: w/c Jun 15, 2026" tags={["Cloud Platform"]} className="rn-upd">
  **Big Peer 1.64.1 delivers better resource management for CDC, improved performance and reliability around evictions, and a range of reliability improvements across sync, the MongoDB Connector, and the query engine.**

  <Icon icon="plus" iconType="solid" horizontal /> **Added:**

  * Better resource management for CDC under heavy workloads
  * Improved performance and reliability under eviction-heavy workloads
  * Kafka consumer stall detection that automatically reconnects when no messages are received, preventing silent hangs during broker failures
  * A new `transport_websocket_connect_timeout` system parameter for tuning WebSocket connect timeouts
  * More predictable cleanup of disconnected document sync sessions, reducing memory usage on long-running deployments

  <Icon icon="arrows-rotate" iconType="solid" horizontal /> **Changed:**

  * The HTTP API `/store/write` endpoint now returns `503 Service Unavailable` when its first command fails to commit due to an internal error, instead of a `200` with an `internalError` count. Failures of later commands in a batch are still reported in the response body so successful results are preserved

  <Icon icon="screwdriver-wrench" iconType="solid" horizontal /> **Fixed:**

  * Improved CDC durability across restarts so transactions are reliably persisted when upquery results are still in flight at the time of a crash
  * Improved hydra-store recovery so Big Peer nodes whose data directory has been wiped now rebuild automatically by replaying the Kafka log or backfilling from peers, instead of stalling in recovery
  * Improved reliability of long-lived Document Sync sessions by addressing an internal subscription bookkeeping issue that could cause them to be disabled due to spurious capacity errors
  * Improved shutdown behavior of the MongoDB Connector when MongoDB is unreachable, so the pod now exits cleanly and is restarted by Kubernetes

  <Icon icon="rocket" iconType="solid" horizontal /> **Performance:**

  * Raised the MongoDB Connector default rate limit for initial sync and resync from 500 to 3000 docs/sec
</Update>

<ReleaseNotesPager />


## Related topics

- [C++ Release Notes](/sdk/v4/release-notes/cpp.md)
- [C# Release Notes](/sdk/v4/release-notes/c-sharp.md)
- [Release Notes](/release-notes.md)
