# v1.45.0: write path Same runs as `v1.45.0-read-path.md`. | request | before p50 ms | after p50 ms | statements before / after | | --- | ---: | ---: | ---: | | batch ingest, 500 fresh rows per request | 166 | 186 | 53 / 50 | Fresh rows were already set-based (v1.44); the benchmark's ingest is all fresh rows, so it shows no gain, as expected. The changes are for re-posts: - **Unchanged `stats:` re-posts** write nothing and start nothing. One read over the batch's `stats:` ids replaces a reconciler transaction (about ten round trips) per row, and an all-unchanged batch no longer refolds, enqueues rollups or PR detection, or marks caches stale. The per-entry status stays `updated` and the summary's `updated` count is unchanged. `tests/integration/routes/measurements-batch-unchanged-stats.test.ts`: four unchanged re-posts take at most 12 statements in total (before: about 40) with zero rollup, invalidation and PR calls; a changed value, a changed device or a tombstoned row still goes through the reconciler. - **Apple Health re-import** skips the UPDATE of a row stored with exactly the values it would write; one read per chunk instead of one UPDATE per row. `tests/integration/apple-health-reimport-unchanged.test.ts`: a re-import of 20 stored rows reports the same per-type counts and sends no UPDATE. - **Narrower invalidation.** The batch route tells the cache how far back it wrote (`touchedFrom`), so closed blocks of older readings stay.