-
Notifications
You must be signed in to change notification settings - Fork 979
Description
Operating System
not relevant
Environment (if applicable)
not relevant
Firebase SDK Version
not relevant
Firebase SDK Product(s)
Firestore
Project Tooling
not relevant
Detailed Problem Description
✨ Feature Request: Add FieldValue.min()
and FieldValue.max()
for atomic numeric and timestamp comparisons
Background
Firestore provides several atomic field transformation helpers such as:
FieldValue.increment(n: number)
FieldValue.arrayUnion(...elements: any[])
FieldValue.arrayRemove(...elements: any[])
These allow developers to update documents without first fetching their current state, which prevents race conditions and reduces read costs.
For example, FieldValue.arrayUnion
appends unique elements if they don’t already exist, and all of these helpers automatically create the field if it doesn’t yet exist.
This makes Firestore updates concise, atomic, and efficient.
Problem
There is currently no built-in way to perform atomic minimum or maximum updates on a field.
Developers must:
- Fetch the document,
- Compare the existing value with the new one client-side, and
- Write the result back.
This introduces both extra read costs and race condition risks in concurrent update scenarios.
Proposed Solution
Add two new atomic field transformations:
FieldValue.min(value)
FieldValue.max(value)
These would compare the provided value against the existing field value and update the field to the smaller or larger of the two.
If the field does not exist, Firestore should initialize it with the provided value (consistent with existing FieldValue semantics).
Use Case
I’m building an ecommerce SaaS platform for rental tracking.
Each inventory item tracks the timestamp of its last rental activity:
item.lastActivityAt = <timestampMilliseconds>
The system must maintain this field as the latest known return date across thousands of concurrent rental line items.
Example
- SKU with quantity = 2
- One unit is rented this morning for 10 weeks (return date = +10 weeks)
- Another unit is rented this afternoon for 1 week
Without atomic max support:
- The later update (1-week rental) could overwrite the earlier one (10-week rental) if both updates happen close together.
The correct logic should be:
item.lastActivityAt = max(existingValue, newReturnDate)
Currently, this requires a fetch-compare-update cycle for every line item, which is both costly and inefficient:
- ~10,000 line items processed per day → ~10,000 extra reads
- Higher latency and risk of stale writes
Benefits
- Enables atomic
max()
andmin()
updates similar to increment() - Avoids race conditions in concurrent write scenarios
- Reduces read/write load by eliminating the need to prefetch documents
- Applies broadly across use cases:
- Tracking latest timestamps (
lastSeenAt
,lastLoginAt
, etc.) - Maintaining running bounds (
minPrice
,maxTemperature
, etc.) - Recording latest event times (
latestUpdateAt
,lastActivityAt
, etc.)
- Tracking latest timestamps (
- Keeps Firestore’s expressive and consistent update API style
Suggested API
await docRef.update({
lastActivityAt: FieldValue.max(newReturnDate)
});
Alternative Considered
Using Cloud Functions or a scheduled reconciliation process to serialize updates and compute maxima server-side.
However, this approach introduces latency, cost, and code complexity.
Having a server-side atomic comparison primitive would be faster, cheaper, and more reliable.
Summary
Adding FieldValue.max()
and FieldValue.min()
would be a natural and powerful extension of Firestore’s atomic update family.
It would dramatically simplify code, reduce operational costs, and prevent concurrency bugs for developers managing high-volume, multi-writer workloads.