My app run in background. If app run in background, is still simultaneous connected with realtimeDB? Or if this app doesn't use realtimeDB for a while, does not count simultaneous connected?
If it's count anyway, can I only get 100,000 user?
Your app is connected to the realtimeDB as long as your listener is active. If you want to stop listening you need to remove the listener according to your needs and to the activity cycle.
For Android you can use this code in your onDestroy() method.
databaseReference.removeEventListener(valueEventListener);
Hope it helps.
I am answering your three part question in order..,
Firebase database library manages the connection to your database in the backend and this starts right away at the start of the app and this starts counting against your simultaneous connections and when this limit reaches the Max Connections limit of 100k any new connections will be dropped until the existing connections drop by either closing the app or app goes offline after a specified time-out or forcefully closing the DB connections by calling
FirebaseDatabase.getInstance().goOffline()
You can however know the whether a given client is connected or not by using the listener at FirebaseDatabase.getInstance().getReference(".info/connected") this however works locally and doesn't explicitly connect to FirebaseDatabase cloud instance., more can be read here
Once you implement the above connection listener you will see that the SDK manages this dynamically in a way that the connections disconnect automatically if there are no listeners attached and if no DB operations like .setValue() are made in the app in last 60 seconds.., but the presence of ValueEventListners will override this and will ensure continuous connectivity with the DB. again this can be overridden and the connection can be severed by explicitly calling FirebaseDatabase.getInstance().goOffline()
Coming to the Max Limit of 100k simultaneous users; as can be seen in Firebase Plans
There is a limit of 100,000 simultaneous connections per database on
the Flame and Blaze plans. See Pricing FAQ for more information.
If you cross this and for scaling you need to increase the limit, you can explicitly ask Google Firebase Team for the support and they will handle this on a case by case basis to ensure your app can scale as required when required..
What is a "simultaneous database connection"?
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 Spark plan limit is 100 and cannot be raised. The Flame and Blaze
plans have a limit of 100,000 simultaneous connections per database.
If you need more than 100,000 simultaneous connections, contact
Firebase support.
This limit isn't the same as the total number of users of your app,
because your users don't all connect at once. We encourage you to
monitor your peak simultaneous database connections and upgrade or add
more databases if needed.
Related
I am looking for max allowed active connections to Firebase Realtime DB in Blaze Plan for below
How many active RtDB listeners (StreamSubscription) from single device
How many active RtDB listeners (StreamSubscription) to single db from all connected devices
In below link I see,
total Simultaneous connections allowed are 200,000
https://firebase.google.com/docs/database/usage/limits
(A simultaneous connection is equivalent to one mobile device, browser tab, or server app connected to the database.)
But I could not find StreamSubscription limit per device, and StreamSubscription limit per db.
I’m using the realtime database for my Flutter app.
I’ve red on the Firebase website the db uses SSL encryption overhead. ~ 3.5kb
My app uses multiple listeners and does a lot of update operations. ~ 3 listeners and 50 updates per user session
Do I have to ‘pay’ 3.5kb with every operation?
Or is the ssl connection only once when the app is launched?
Thanks in advance !
Contacted firebase support about this:
"The Admin SDK for Node uses a socket to connect to the Firebase
database. It does not use the REST API. Bandwidth while negotiating
the HTTPS/WebSocket connection is billable traffic here too. The
building of this connection from Cloud Functions to the Database
happens when a new container is created. This can be upon the first
deployment of the project's functions, after a period of inactivity,
or when the Cloud Functions needs to be scaled-up due to high
activity."
According to firestore documentation:
a transaction is a set of read and write operations on one or more documents.
Also:
Transactions will fail when the client is offline.
Now the limitation in firestore is that:
In Cloud Firestore, you can only update a single document about once per second, which might be too low for some high-traffic applications.
So using cloud functions and running transactions to increment/decrement counters when the traffic is high will fail.
So they have discussed to use the approach of distributed counters.
According to the algorithm of distrbuted counter:
create shards
choose a shard randomly
run a transaction to increment/decrement the counter
get all the shards and aggregate the
result to show the value of a counter
Scenerio:
consider you have a counter which is to be updated when a document is added and that counter is being displayed in the UI. Now for good UX, I cannot block the UI when network is offline. So I must allow creation/updation of documents even when client is offline and sync these changes once client is online so that everyone else listening to these changes receive the correct value of the counter.
Now transactions fail when the client is offline.
So my question for best user experience (even when offline) is:
Do you really require a transaction to increment a counter? I know
transactions ensure that writes are atomic and are either
successful/unsuccessful and prevent partial writes. But what's the
point when they fail offline? I was thinking maybe write them to local cache and sync it once the network is back online.
Should this be done via client sdks of via cloud functions?
Do you really require a transaction to increment a counter?
Definitely yes! Because we are creating apps that can be used in a multi user environment, transactions are mandatory, so we can provide consistent data.
But what's the point when they fail offline?
When there is a loss of network connectivity (there is no network connection on user device), transactions are not supported for offline use. This is because a transaction absolutely requires round trip communications with server in order to ensure that the code inside the transaction completes successfully. So, transactions can only execute when you are online.
Should this be done via client sdks of via cloud functions?
Please note, that the Firestore SDK for Android has a local cache that's enabled by default. According to the official documentation regarding Firestore offline persistence:
For Android and iOS, offline persistence is enabled by default. To disable persistence, set the PersistenceEnabled option to false.
So all read operations will come from cache if there are no updates on the server. So Firestore provides this feature for handle offline data.
You can also write a function in Cloud Function that will increment the counter while a new document is added or to decrement the conter while a document is deleted.
I also recommend you to take a look:
How to count the number of documents under a collection in Firestore?
So you may also consider using Firebase realtime database for that. Cloud Firestore and Firebase realtime database work very well together.
Edit:
It allows one to upvote the answer even when the device is offline. After the network is online, it syncs to the server and the counter is updated. Is there a way i can do this in firestore when the device is offline.
This is also happening by default. So if the user tries to add/delete documents while offline, every operation is added to a queue. Once the user regains the connection, every change that is made while offline, will be updated on Firebase servers. With other words, all queries will be commited on the server.
Cloud fnctions are triggered only when the change is received and that can only happen when the device is online.
Yes, that correct. Once the device regains the network connection, the document is added/deleted from the database, moment in which the function fires and increases/decreases the counter.
Edit2:
Suppose I have made around 100 operations offline, will that not put a load on the cloud functions when the device comes online? What's your thought on this?
When offline, pending writes that have not yet been synced to the server are held in a queue. If you do too many write operations without going online to sync them, that queue will grow fast and it will not slow down only the write operations it will also slow down your read operations. So I suggest use this database for its online capabilities.
Regarding Cloud Functions for those 100 offline operations, there will be no issues. Firebase servers work very well with concurent operations.
In my project I‘m using the realtime database as well as the Firestore database. My cloud functions triggers when a document is added to a specific collection inside my Firestore database. The function then writes to my realtime database to update some statistics. I noticed that even if no user is connected to my realtime database, the count of concurrent connections increases when the cloud function writes to the realtime database. Does this mean that my cloud functions count as concurrent connections and will decrease the amount of users that can connect to my realtime database at once as there is a limit of 100k concurrent connections?
You'll incur one connection for each server instance running your functions. It is not one per individual function invocation. So, if it only requires one server instance to run your function, then it will only cost one connection. When a server instance is automatically deallocated from your project, its connection will go away.
You will need an extremely busy set of functions in order to make a real dent in your 100K concurrent connection cap for Realtime Database. I wouldn't worry about it.
On Firebase pricing page it has been stated that:
What is a "simultaneous database connection"?
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 Spark plan limit is 100 and cannot be raised. The Flame and Blaze plans have a limit of 100,000 simultaneous connections per database. If you need more than 100,000 simultaneous connections, contact Firebase support.
This limit isn't the same as the total number of users of your app, because your users don't all connect at once. We encourage you to monitor your peak simultaneous database connections and upgrade or add more databases if needed.
On the last paragraph, what does it mean by adding more databases? Because as far as I know there is only one database in a project and multiple nodes inside that database. Does it mean creating multiple projects?
Yes, it means having a separate project as you can only have 1 database per project.
Update (2018 - 2019):
As of writing, Firebase now supports multiple Realtime Database instances per project. The database limits are now 100 for Spark, 200K for Flame and 200K per database for Blaze.
There can be multiple FirebaseApp instances. One will be initialised by default from the json file values, and the other you can create yourself, e.g.
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("1:530266078999:android:481c4ecf3253701e") // Required for Analytics.
.setApiKey("AIzaSyBRxOyIj5dJkKgAVPXRLYFkdZwh2Xxq51k") // Required for Auth.
.setDatabaseUrl("https://project-1765055333176374514.firebaseio.com/") //Required for RTDB.
.build();
FirebaseApp.initializeApp(this /* Context */, options, "secondary"); //
Retrieve my other app.
FirebaseApp app = FirebaseApp.getInstance("secondary");
// Get the database for the other app.
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(app);