skip to Main Content

In short: Is there some kind of cold start when connecting to Firestore directly from Client SDK

Hey. I’m using Firestore client sdk in Andoid and IOS application through @react-native-firebase.
Everything works perfectly but I have noticed weird behavior I haven’t found explanation.
I have made logging to see how long it takes from user login to retrieve uid corresponding data from Firestore and this time has been ~0.4-0.6s. This is basically the whole onAuthStateChanged workflow.

    let userLoggedIn: Date;
    let userDataReceived: Date;
    auth().onAuthStateChanged(async (user) => {
        userLoggedIn = new Date();
    
        const eventsRetrieved = async (data: UserInformation) => {
          userDataReceived = new Date();

          getDataDuration = `Get data duration: ${(
            (userDataReceived.getTime() - userLoggedIn.getTime()) /
            1000
          ).toString()}s`;

         console.log(getDataDuration)

          // function to check user role and to advance timing logs
          onUserDataReceived(data);
        };
    
        const errorRetrieved = () => {
          signOut();
          authStateChanged(false);
        };
    
        let unSub: (() => void) | undefined;
    
        if (user && user.uid) {
    
          const userListener = () => {
            return firestore()
              .collection('Users')
              .doc(user.uid)
              .onSnapshot((querySnapshot) => {
                if (querySnapshot && querySnapshot.exists) {
                  const data = querySnapshot.data() as UserInformation;
                  data.id = querySnapshot.id;
                  eventsRetrieved(data);
                } else errorRetrieved();
              });
            };
    
          unSub = userListener();
       } else {
          if (typeof unSub === 'function') unSub();
          authStateChanged(false);
       }
    });

Now the problem. When I open the application ~30-50 minutes after last open the time to retrieve uid corresponding data from Firestore will be ~3-9s. What is this time and why does it happen? And after I open the application right after this time will be low again ~0.4-0-6s.
I have been experiencing this behavior for weeks. It is hard to debug as it happens only on build application (not in local environments) and only between +30min interval.

Points to notice

  • The listener query (which I’m using in this case, I have used also simple getDoc function) is really simple and focused on single document and all project configuration works well. Only in this time interval, which seems just like cold start, the long data retrieval duration occurs.
  • Firestore Rules should not be slowing the query as subsequent request are fast. Rules for ‘Users’ collection are as follows in pseudo code:
function checkCustomer(){
  let data = 
  get(/databases/$(database)/documents/Users/$(request.auth.uid)).data;
      return (resource.data.customerID == data.customerID);
    } 

match /Users/{id}{
  allow read:if
    checkUserRole() // Checks user is logged in and has certain customClaim
    && idComparison(request.auth.uid, id) // Checks user uid is same as document id
    && checkCustomer() // User can read user data only if data is under same customer
  }
  • Device cache doesn’t seem to affect the issue as application’s cache can be cleaned and the "cold start" still occurs
  • Firestore can be called from another environment or just another mobile device and this "cold start" will occur to devices individually (meaning that it doesn’t help if another device opened the application just before). Unlike if using Cloud Run with min instances, and if fired from any environment the next calls right after will be fast regardless the environment (web or mobile).

EDIT
I have tested this also by changing listener to simple getDoc call. Same behavior still happens on a build application. Replacing listener with:

await firestore()
  .collection('Users')
  .doc(user.uid)
  .get()
      .then(async document => {
        if (document.exists) {
          const data = document.data() as UserInformation;
          if (data) data.id = document.id;
          eventsRetrieved(data);
        }
      });

EDIT2
Testing further there has been now 3-15s "cold start" on first Firestore getDoc. Also in some cases the timing between app open has been only 10 minutes so the minimum 30 min benchmark does not apply anymore. I’m going to send dm to Firebase bug report team to see things further.

2

Answers


  1. Chosen as BEST ANSWER

    In the end I didn't find straight answer why this cold start appeared. I ended up changing native Client SDK to web Client SDK which works correctly first data fetch time being ~0.6s (always 0.5-1s). Package change fixed the issue for me while functions to fetch data are almost completely identical.


  2. Since you’re using React Native, I assume that the documents in the snapshot are being stored in the local cache by the Firestore SDK (as the local cache is enabled by default on native clients). And since you use an onSnapshot listener it will actually re-retrieve the results from the server if the same listener is still active after 30 minutes. From the documentation on :

    If offline persistence is enabled and the listener is disconnected for more than 30 minutes (for example, if the user goes offline), you will be charged for reads as if you had issued a brand-new query.

    The wording here is slightly different, but given the 30m mark you mention, I do expect that this is what you’re affected by.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search