title: Firebase cloud functions is very slow
body: <p>We're working on an application that uses the new firebase cloud functions. What currently is happening is that a transaction is put in the queue node. And then the function removes that node and puts it in the correct node. This has been implemented because of the ability to work offline. </p>
  
  <p>Our current problem is the speed of the function. The function itself takes about 400ms, so that's alright. But sometimes the functions take a very long time (around 8 seconds), while the entry was already added to the queue. </p>
  
  <p>We suspect that the server takes time to boot up, because when we do the action once more after the first. It takes way less time. </p>
  
  <p>Is there any way to fix this problem? Down here i added the code of our function. We suspect there's nothing wrong with it, but we added it just in case.</p>
  
  <pre><code>const functions = require('firebase-functions');
  const admin = require('firebase-admin');
  const database = admin.database();
  
  exports.insertTransaction = functions.database
      .ref('/userPlacePromotionTransactionsQueue/{userKey}/{placeKey}/{promotionKey}/{transactionKey}')
      .onWrite(event =&gt; {
          if (event.data.val() == null) return null;
  
          // get keys
          const userKey = event.params.userKey;
          const placeKey = event.params.placeKey;
          const promotionKey = event.params.promotionKey;
          const transactionKey = event.params.transactionKey;
  
          // init update object
          const data = {};
  
          // get the transaction
          const transaction = event.data.val();
  
          // transfer transaction
          saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey);
          // remove from queue
          data[`/userPlacePromotionTransactionsQueue/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = null;
  
          // fetch promotion
          database.ref(`promotions/${promotionKey}`).once('value', (snapshot) =&gt; {
              // Check if the promotion exists.
              if (!snapshot.exists()) {
                  return null;
              }
  
              const promotion = snapshot.val();
  
              // fetch the current stamp count
              database.ref(`userPromotionStampCount/${userKey}/${promotionKey}`).once('value', (snapshot) =&gt; {
                  let currentStampCount = 0;
                  if (snapshot.exists()) currentStampCount = parseInt(snapshot.val());
  
                  data[`userPromotionStampCount/${userKey}/${promotionKey}`] = currentStampCount + transaction.amount;
  
                  // determines if there are new full cards
                  const currentFullcards = Math.floor(currentStampCount &gt; 0 ? currentStampCount / promotion.stamps : 0);
                  const newStamps = currentStampCount + transaction.amount;
                  const newFullcards = Math.floor(newStamps / promotion.stamps);
  
                  if (newFullcards &gt; currentFullcards) {
                      for (let i = 0; i &lt; (newFullcards - currentFullcards); i++) {
                          const cardTransaction = {
                              action: "pending",
                              promotion_id: promotionKey,
                              user_id: userKey,
                              amount: 0,
                              type: "stamp",
                              date: transaction.date,
                              is_reversed: false
                          };
  
                          saveTransaction(data, cardTransaction, userKey, placeKey, promotionKey);
  
                          const completedPromotion = {
                              promotion_id: promotionKey,
                              user_id: userKey,
                              has_used: false,
                              date: admin.database.ServerValue.TIMESTAMP
                          };
  
                          const promotionPushKey = database
                              .ref()
                              .child(`userPlaceCompletedPromotions/${userKey}/${placeKey}`)
                              .push()
                              .key;
  
                          data[`userPlaceCompletedPromotions/${userKey}/${placeKey}/${promotionPushKey}`] = completedPromotion;
                          data[`userCompletedPromotions/${userKey}/${promotionPushKey}`] = completedPromotion;
                      }
                  }
  
                  return database.ref().update(data);
              }, (error) =&gt; {
                  // Log to the console if an error happened.
                  console.log('The read failed: ' + error.code);
                  return null;
              });
  
          }, (error) =&gt; {
              // Log to the console if an error happened.
              console.log('The read failed: ' + error.code);
              return null;
          });
      });
  
  function saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey) {
      if (!transactionKey) {
          transactionKey = database.ref('transactions').push().key;
      }
  
      data[`transactions/${transactionKey}`] = transaction;
      data[`placeTransactions/${placeKey}/${transactionKey}`] = transaction;
      data[`userPlacePromotionTransactions/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = transaction;
  }
  </code></pre>