Clarify the Firebase Connections

Clarify the Firebase connections

In your first scenario - the short answer is yes. As long as your users keep the screen on where you have a Firebase connection that allows them to comment/read comments - you will have one concurrent connection per screen.

In your second scenario - this depends on how you develop your app. The Firebase API does provide you with the goOffline and goOnline methods (https://www.firebase.com/docs/ios-api/Classes/Firebase.html#class_methods) which give you control over your connection. If you want to go offline for 5 minutes, then briefly come back online to check scores and then go offline again, then you'd only hold a connection for a short duration.

Concurrent connections are just that - connections established at the same time. So if you have 3 people using your app to check scores, but user 1's app goes online at 12:00 PM and the connection lasts for 5 seconds, then user 2's app goes online at 12:01 PM for 5 seconds, and user 3's app goes online at 12:02 PM for 5 seconds then you've only ever had 1 concurrent connection.

If on the other hand, all 3 users' apps go online at 12:00 PM for 5 seconds then you'll have 3 concurrent connections.

You could potentially use this same goOffline/goOnline strategy with your first scenario, but that may detract from the experience if your users are expecting to be chatting about a game in near real-time.

Clarification on usage of realtime database

The usage stats indeed show the maximum number of users that were connected at any one time during that hour.

It is not the total number of users that connected during that hour. If you want to know that, you can easily build it by having each user write an event to the database when it connects or by using a product like Firebase Analytics.

Clarification on Firebase Cloud Messaging simultaneous connections?

The limit on "simultaneous database connection" refers the usage of the database API.

To receive notifications (whether the app is in background, open, or closed doesn't matter) through FCM (or GCM is the same) your app doesn't need to keep any connection open.

The firebase SDK together with the each platform operative system will take care of that.

What counts as a firebase database connection?

From the frequently asked questions:

A simultaneous connection is equivalent to one mobile device, browser tab, or server app connected to the database. Firebase imposes hard limits on the number of simultaneous connections to your app's database. These limits are in place to protect both Firebase and our users from abuse.

The SDK connects to the server the first time that you try to access data from (or write data to) the database. The connection stays open for as long as the client has an active listener (so observe in your case) or until about 5 minutes after the last read or write operation.

You can also explicitly control the connection by calling goOffline and goOnline in your code.

How the Connection is calculated in Firebase

This question was bugging me ever since I ran through the thinkster.io angular+firebase tutorial and I saw my firebase analytics tab showing a peak concurrent of 6 even though I only remember having the one page open. I looked back at the code and thought it could be to do with how the tutorial has you create a new Firebase(url) for each location in your firebase.

I wanted to test the difference between creating a new Firebase(url) vs taking the root reference and then accessing the .child() location. My theory was that new Firebase(url) would create a new connection each time, while .child() would re-use the existing connection.

Setup

  • Created two new firebases each with identical data
  • Setup an angularjs project using yeoman
  • Included angularfire

Code

For simplicity, I just put everything in the main controller of the generated code.

To test out the connections created with new Firebase() I did the following:

$scope.fb_root = $firebase(new Firebase(FBURL_NEW));
$scope.fb_root_apps = $firebase(new Firebase(FBURL_NEW + '/apps'));
$scope.fb_root_someApp = $firebase(new Firebase(FBURL_NEW + '/apps/someApp'));
$scope.fb_root_users = $firebase(new Firebase(FBURL_NEW + '/users'));
$scope.fb_root_mike = $firebase(new Firebase(FBURL_NEW + '/users/mike'));

To test out the connections created with ref.$child() I did the following:

$scope.fb_child = $firebase(new Firebase(FBURL_CHILD));
$scope.fb_child_apps = $scope.fb_child.$child("apps");
$scope.fb_child_someApp = $scope.fb_child_apps.$child("someApp");
$scope.fb_child_users = $scope.fb_child.$child("users");
$scope.fb_child_mike = $scope.fb_child_users.$child("mike");

I then bound these objects in my view so I can see them, and I played around with updating data via my firebase forge and watching the data update live on my app.

Results

I opened up my local app into 17 browser tabs, hoping that a large number of tabs would exaggerate any differences between the connection methods.

What I found is that each tab only opened up one single web socket connection back to firebase for each firebase db. So at the end of the test, both methods resulted in the same peak count of 17 connections.

Conclusion

From this simple test I think it's safe to say that the Firebase JS library does a good job of managing its connection.

Regardless of your code calling new Firebase() a bunch of times, or by referencing child locations via .child(), the library will only create a single connection as far as your metering is concerned. That connection will stay online for as long as your app is open.

So in your example - yes I believe you will see 6 concurrent connections, 1 for the app where someone is sending the message, and 5 for the apps receiving the message.

Update

One other thing worth mentioning is that Firebase measures connections for paid plans based on the 95th percentile of usage during the month. This is listed in the FAQ section of their Pricing page @ https://www.firebase.com/pricing.html

Update 11-Mar-16: Firebase no longer appears to measure connections based on 95th %. Instead, the 101st concurrent connection is denied.

https://www.firebase.com/pricing.html :

All our plans have a hard limit on the number of database connections.
Our Free and Spark plans are limited to 100. The limit cannot be
raised. All other plans have a courtesy limit of 10,000 database
connections. This can be removed to permanently allow Unlimited
connections if you email us at firebase-support@google.com.. The
reason we impose this courtesy limit is to prevent abuse and to ensure
that we are prepared to handle our largest customers. Please contact
us at least 24 hours in advance so we can lift this limit and ensure
we have enough capacity available for your needs.

Simultaneous connections in firebase

If there are no active listeners for a minute, the Firebase client will indeed close its connection to the server.

In your code you call loadStoreDetails attaches a listener with addValueEventListener from onCreate. Since you never remove that listener, it will stay active permanently from the moment ThreeFragment is created until the program exits.

To prevent this, and ensure the data is only synchronized (and the connection kept open) while the user has the fragment open, detach the listener in onDestroyView or onDestroy of the fragment.

For that, add a member field to the fragment:

ValueEventListener mFragmentListener;

Then keep a reference to the listener when you attach it:

mFragmentListener = mdatabase.limitToLast(20).addValueEventListener(valueEventListener);

And finally remove the listener when the fragment is destroyed:

@Override
public void onDestroyView() {
mdatabase.limitToLast(20).removeEventListener(mFragmentListener);
}

On a separate note: the call to mdatabase.keepSynced(false); is not needed in your code, as that is the default behavior already.

Firebase concurrent connections?

I have no idea how you got from that accepted answer by @MikePugh to your conclusions. The text:

Concurrent connections are just that - connections established at the same time. So if you have 3 people using your app to check scores, but user 1's app goes online at 12:00 PM and the connection lasts for 5 seconds, then user 2's app goes online at 12:01 PM for 5 seconds, and user 3's app goes online at 12:02 PM for 5 seconds then you've only ever had 1 concurrent connection.

I added emphasis on the parts that you seem to have skipped in your copy.

In the example Mike gave, each user was connected only for a very short time. So there was never more than a single concurrent connection. In fact, for the majority of the day (23 hours 59 minutes 45 seconds) there were 0 connections. Given that Firebase bills at the 95th percentile, you'd be billed for 0 concurrent connections (if they'd offer such a tier).

You indicate that your users stay connected for 24 hours, which leads to 3 concurrent connections from 12:02 to midnight. So you'd have 3 concurrent connections for the majority of the time.

Firebase unexpected number of concurrent connections

Here is what I get after discussing with the support team:

here are other common use cases that can add up to the number of
connections in your app:

  • Opening your web app in multiple tabs on your browser (1 connection per tab)
  • Accessing the Realtime Database dashboard from the Firebase Console (1 connection per tab)
  • Having Realtime Database triggers

So Realtime Database triggers appeared to be my case.

Further discussion revealed the following:

In the case of uploading 200 data points which each trigger a
function, any number of concurrent connections between 1 and 200 is
possible. It all depends on how Cloud Functions scales. In an extreme
case it could just be one instance that processes all 200 events one
at a time. In another extreme case the Cloud Functions system could
decide to spin up 200 new server instances to handle the incoming
events. There's no guarantee as to what will happen here, Cloud
Functions will try to do the right thing. Each case would cost the
user the same amount on their Cloud Functions bill. What's most likely
in a real application (where it's not a complete cold start) is
something in the middle.

There's no need to worry about the number of concurrent connections
from Cloud Functions to RTDB. Cloud Functions would never spin up
anywhere near 100k server instances. So there's no way Cloud Functions
would eat up the whole concurrency limit. That would only happen if
there are many users on the client app accessing your database
directly from their devices.

So the described behavior in my question seems to be expected and it will not come any close to the limit of 100k connections from server side.



Related Topics



Leave a reply



Submit