@powersync/common: clarify or preserve SyncStreamStatus.subscription.lastSyncedAt precision
Package
@powersync/common@1.52.0 (latest on npm as of 2026-05-05)
Disclosure
This report is distilled from behavior reproduced in a staged production environment. Product-specific data, names, and identifiers were redacted and the public repro/draft was edited with AI assistance. The repro and issue text were reviewed and validated by a human before submission.
Summary
SyncStatus.forStream(...).subscription.lastSyncedAt is exposed as a JavaScript Date, but the value appears to be derived from a whole-second last_synced_at core timestamp:
lastSyncedAt: core.last_synced_at != null ? new Date(core.last_synced_at * 1000) : null
That means subsecond precision from caller-side cutoff timestamps is lost. This may be intended, but I could not find documentation for the precision contract.
Minimal reproduction
git clone https://github.com/whygee-dev/powersync-common-sync-stream-last-synced-at-precision-repro.git
cd powersync-common-sync-stream-last-synced-at-precision-repro
npm install
npm test
Observed output:
expected syncedAfter: 2026-04-19T10:00:00.750Z
core last_synced_at: 1776592800
reported lastSyncedAt: 2026-04-19T10:00:00.000Z
precision loss ms: 750
reproduced: stream subscription lastSyncedAt reports whole-second precision
The repro constructs a SyncStatus with an internal stream subscription whose last_synced_at is an epoch-second value, then reads it back through status.forStream(...).subscription.lastSyncedAt.
Expected behavior
One of these should be true:
- stream status timestamps preserve subsecond precision when exposed as JavaScript
Date values; or
- the API documentation states that stream
lastSyncedAt has whole-second precision, so callers know to floor/round cutoff timestamps or compare with tolerance.
Actual behavior
The public value is a Date, but it can be rounded down to the beginning of the second. Code that waits for a stream to sync after a JavaScript timestamp such as 2026-04-19T10:00:00.750Z can see:
subscription.hasSynced === true
subscription.lastSyncedAt === 2026-04-19T10:00:00.000Z
and keep waiting because lastSyncedAt < syncedAfter.
Impact
Applications that subscribe to streams and then wait for subscription.hasSynced plus subscription.lastSyncedAt >= syncedAfter can get false negatives whenever syncedAfter contains milliseconds.
The downstream workaround is to floor the cutoff to whole seconds before comparing. The unclear part is whether that workaround is required by design or compensating for a precision bug.
Question
Is whole-second precision for sync stream lastSyncedAt intended? If yes, can this be documented on the stream status/subscription APIs? If not, can the core status preserve subsecond precision?
@powersync/common: clarify or preserveSyncStreamStatus.subscription.lastSyncedAtprecisionPackage
@powersync/common@1.52.0(lateston npm as of 2026-05-05)Disclosure
This report is distilled from behavior reproduced in a staged production environment. Product-specific data, names, and identifiers were redacted and the public repro/draft was edited with AI assistance. The repro and issue text were reviewed and validated by a human before submission.
Summary
SyncStatus.forStream(...).subscription.lastSyncedAtis exposed as a JavaScriptDate, but the value appears to be derived from a whole-secondlast_synced_atcore timestamp:That means subsecond precision from caller-side cutoff timestamps is lost. This may be intended, but I could not find documentation for the precision contract.
Minimal reproduction
Observed output:
The repro constructs a
SyncStatuswith an internal stream subscription whoselast_synced_atis an epoch-second value, then reads it back throughstatus.forStream(...).subscription.lastSyncedAt.Expected behavior
One of these should be true:
Datevalues; orlastSyncedAthas whole-second precision, so callers know to floor/round cutoff timestamps or compare with tolerance.Actual behavior
The public value is a
Date, but it can be rounded down to the beginning of the second. Code that waits for a stream to sync after a JavaScript timestamp such as2026-04-19T10:00:00.750Zcan see:and keep waiting because
lastSyncedAt < syncedAfter.Impact
Applications that subscribe to streams and then wait for
subscription.hasSyncedplussubscription.lastSyncedAt >= syncedAftercan get false negatives wheneversyncedAftercontains milliseconds.The downstream workaround is to floor the cutoff to whole seconds before comparing. The unclear part is whether that workaround is required by design or compensating for a precision bug.
Question
Is whole-second precision for sync stream
lastSyncedAtintended? If yes, can this be documented on the stream status/subscription APIs? If not, can the core status preserve subsecond precision?