← Case studies
About this account

Published by the Marionette project. The migration combined human direction and agent assistance as the framework and its guidance evolved. It was not a controlled agent-development experiment.

02 / ROUNDINGWELL

RoundingWell: a mature application moves to Marionette v5

RoundingWell migrated from Backbone.Marionette to v5 while preserving its care-team workflows. Clearer application boundaries and faster measured worklist operations provide a foundation for continued development.

RoundingWell’s white symbol and wordmark in a blue rounded panel beside Marionette’s white symbol and wordmark in a red rounded panel. An established product. A new chapter.
RoundingWell × Marionette · View full size

An application already at work.

RoundingWell helps care teams organize workflows, worklists, forms, and follow-up. Its frontend is a substantial application used in daily work, with years of product decisions and an established browser-test suite behind it.

The migration preserved that investment while removing application jQuery and Marionette.Toolkit. Backbone data and routing, Handlebars templates, and the service layer stayed. Explore the application · Runtime integration

RoundingWell action-card views with synthetic Alice and Bob records, assignment controls, dates, and checkboxes.
Real action-card views with synthetic data, captured in the worklist benchmark harness. Open full size.

Refresh the results. Keep the context.

Change a worklist filter while a patient sidebar is open. The results need to refresh; the surrounding page and sidebar should stay in place. Navigate away, and unfinished work must lose permission to update the replacement screen.

The migration gives the page, results, and sidebar separate owners. The page coordinates its children; the results application owns selection, bulk editing, status, and list content. These boundaries give loading, refresh, and cleanup a specific home. Page composition · Results ownership

With Marionette v5, the application replaces its local request coordinator with prepareStart and retained restart(): the results container stays mounted while replacement data loads. This gives refresh and cancellation a standard lifecycle, with less application-specific coordination. Lifecycle source

Protect the workflow.

An early migration revision passed 304 E2E tests across 35 existing specs, with two scenarios passing on retry. The migration also adds coverage for retaining cards during refresh, retrying failed loads, and keeping sidebar navigation available while data loads.

Those user-visible contracts give future changes something concrete to preserve. Read the loading scenarios · Verification record

What got faster?

A September 23 benchmark compared real worklist Views on v4 and v5 branches, using synthetic data and each branch’s actual templates, styles, and nested controls.

Median milliseconds · 500 rows · 15 paired observations
Operationv4 branchv5 branchChange
Render editable action cards244.5186.323.8% less time
Filter out half the action cards60.69.484.5% less time
Destroy the action list62.443.829.8% less time
Reverse flow-card order104.2109.55.1% more time

Rendering, filtering, and teardown improved. Flow-card reversal became slightly slower because increased style/layout cost outweighed cheaper synchronous work.

These historical results used a v5 beta build and have not been rerun against the final migration. Timings include synchronous work and forced style/layout, excluding network and the full app shell. Application and adapter changes accompany the framework change, so these results cannot isolate Marionette’s contribution. All 92 comparisons and uncertainty ranges.

Give the next change a home.

RoundingWell’s migration shows how an established application can preserve useful product behavior while making ownership clearer. A sidebar change, loading state, or late-response bug has a specific place to investigate and a workflow to test.

For another mature app, start with one demanding workflow: decide what stays mounted, what refreshes independently, and who owns unfinished work. Preserve its behavioral checks, then measure its expensive interactions.

Evidence and methodology

Source links pin the initial migration and lifecycle refinement separately. The refined source revision is 870da88e24b7b14bf2563b3325199a4534c45aee. The verification record reports passing component/E2E CI and 100% instrumented line/branch coverage, with documented exclusions and narrow ignores. Application tests and benchmarks were not rerun for this article; their historical results do not establish production deployment or defect-free behavior.

Benchmark: September 23, 2026 (Asia/Seoul), Apple M2 Pro, 16 GiB RAM, headless Chrome 153.0.8010.53, 1440 × 1000, unthrottled, warm caches. Exact package versions, source pins, and file hashes identify both benchmark builds.

Each configuration used 15 alternating branch pairs after two discarded warmups, with no outliers removed. The preserved data contains 360 measured sequences and 2,760 operation timings. Recorded assertions cover list behavior and teardown. An earlier run missing global design tokens was excluded. Exploratory bootstrap ranges describe local variation; cold startup, full navigation, mobile use, live APIs, paint timing, and memory retention were not measured. At 5,000 rows, rendering still took seconds on both branches.

Full method and limits · Complete summary · Raw 100–1,000-row samples · Raw 5,000-row samples. The table reads the preserved CSV directly. The hero pairs the RoundingWell and Marionette vector logos; the worklist image is a browser capture with synthetic data.