Fuck you Firebase, what a load of bull shit. Implying your database can scale infinitely because we can manually shard our data is like calling McDonalds an all you can eat restaurant because I can keep buying more chicken nuggets.
I've yet to meet anyone who has used Firebase on a large scale project and been happy with it. Firebase is a toy at best, IMO.
I honestly feel a bit bad for the development team at Firebase, they actually built something really cool that has a lot of potential. The problem I have is that someone took this cool project and basically lied to the public about its capabilities.
I also got similar advice to shard my users or something.
So right now, we have crossed that limit and are unable to know how many users are on our system. Their server just fails and takes down the DB for 10 or so mins if I do that query.
Firebase is good for MVPs and prototypes but not at all scalable.
I don't know if you are aware, but their DB can't handle more than 1000 requests/sec, so if you are iterating through a list of nodes and requesting data for each one you can hit that limit (not a good practice, but sometimes you have to). Additionally, once you hit that limit, the DB slows down but keeps accepting requests meaning, if you keep hitting it, even at a slower rate you make the backlog worse. Seriously, be very very careful not to go over that limit, we found out the hard way.
Running a query takes down the db?
That sounds like a major problem. How can that happen?
Maybe returning incorrect or incomplete results due to sharding... But taking the db down? That's very... Unexpected.
Oh come on, it was a startup. The same people who made the tool told the lies (if that's what they were). Now under Google, this is still the case - the original founders now lead the Firebase department if I'm not mistaken. I'm pretty sure they have influence over the marketing messages.
And then people are surprised when I advise them to avoid startup products.
It's the classic tragedy of the commons; lying your way into an acquihire is a win for the successful founders, and a loss for the everyone else in the ecosystem, as more and more people grow sick of being played that way.
I can roll my own using Rails but I'm trying to avoid that.
That is a huge number of concurrent users though.
Our app has multiple millions of users and we wanted to add a small feature which we were going to use Firebase to back. We ended up having to go back to the drawing board when we started a gradual roll out and hit that limit pretty quickly.
The big problem for me using a serverless architecture was constantly having to bend over backwards with the security model of firebase to accomplish things that are very simple when you have a layer of business logic under your own control on the server between the client and the database. Once the client can write whatever they want to the database, every single operation becomes an order of magnitude more difficult to develop as you imagine what ways the client could mess with you, and develop security rules to prevent that. The result-- and this was the dealbreaker for me-- is designing the backend data structure around security, instead of designing the backend data structure around the vitally important goal of supporting your business use cases.
In the end I decided it's better to just pony up and make a server. Service Fabric, and particularly the distributed actor model, gives me the realtime functions and reliability I want for my use cases without making me administer servers.
[1] https://docs.microsoft.com/en-us/azure/cosmos-db/introductio...
[2] https://azure.microsoft.com/en-us/services/service-fabric/
Providing a lot of flexibility to the client when querying the server eliminates a lot of server side work that would normally be required in order to implement new user stories.
It does require a bit of a mindset change so I am often having to force myself to try doing things in a different way to my first assumption.
Its a shame more people don't realize what a gold mine of a piece of technology it is.
You're right that neither SC not Deepstream support long polling fallbacks but there are some very good architectural reasons for this. Both SC and Deepstream used to support HTTP long polling fallbacks via engine.io in the past but both projects independently decided to stop doing it after years of experimentation and feedback.
Now that WebSockets are well supported in all major web browsers and HTTPS has become even more prevalent (so corporate proxies are no longer a problem), the extra load balancing complexity, performance costs and the DoS vulnerabilities of long polling are no longer worth it.
I can definitely appreciate the additional complexity of supporting the fallback. I imagine that elixir's OTP and STM functionality lowers the bar for handling the extra state management across multiple nodes.
Not that that takes anything away from your argument, but given that this topic is about Firebase, readers could get the impression that it offers the same.
That said, I like Phoenix Channels too, and the long polling support is a must-have for us. The "very good architectural reasons" for not doing this, as quoted by @jondubois in a sister comment, are nice, but if that means that 10% of our audience can't use our product then that's a show stopper. I love that Phoenix takes these cases seriously.
That said, Phoenix Channels are a mess when it comes to documentation and terminology. It's built on only two terms, "socket" and "channel", both of which mean 2 to 3 different but related things.
(background: at https://talkjs.com we recently moved our realtime stuff from Firebase to Phoenix Channels)
https://ashleyconnor.co.uk/2016/03/06/deploying-a-phoenix-ap...
- Serverless is a great goal, but only works for low complexity apps. We've designed deepstream explicitly not to take the server away, but as a layer that sits in between backend and frontend and allows servers and clients to connect and exchange data.
- The same is true for auth. DeepstreamHub comes with similar built in auth and usermanagement functions as Firebase, but more importantly comes with a Webhook auth strategy that forwards any login data and associated connection info (IP, Cookies etc) to a HTTPS endpoint of the users choosing. Depending on the returned status code the connection is either granted or denied. In addition the auth server can also return client specific metadata that's either forwarded to the client upon login or used within permission rules to determine access rights
- Querying. This has so far not been a strongpoint of deepstream either, but we'll soon be releasing a blazingly fast realtime graphql implementation to address this. More details here: https://deepstreamhub.com/blog/deepstream-3.0-release/
Since I think DS doesn't support more than one level of nested data. Is there an easy way?
e.g.: from chain.js:
// TODO: BUG! Handle plural chains by iterating over them.
(obj_has(next, 'put')){ // potentially incorrect?
if(u !== next.put){ // potentially incorrect? Maybe?
A lot of comments like: // ugly hack for now.
1) API backend using Google Cloud Endpoints deployed in GKE. Still using firebase Auth.
2) React SPA served from firebase hosting. Using FirebaseAuthUI
One thing I continue to be astonished about is how difficult it remains to build a real apps (ssl, auth, persistence, packaging, deployment) as a one person team.
What is wrong with a simple rails/spring/django project hosted on heroku/elasticbeanstalk? Ssl, auth, persistence, packaging and deployment are all covered and easy.
Of you want a bit more control you can swap heroku/eb for a vps and use ansible for deloyment which is my preferred method for one person projects
Edit: 9 since you specified ssl too (thank you Let's Encrypt), and 10 for real-time support, and 11-20 for all the devops stuff that I should know more about.
- completely use firebase
- completely use AppEngine
So, you would get easy packaging, ssl, deployment, infrastructure maintenance..
1) Relational databases are more flexible: you model your data according to the actual "relations" between them, instead of how you want to query them. This makes it easier to add new views/queries to your application.
2) Joins are necessary
3) In a very short time, you need complex authentication logic and it is very hard to do it without looking at the requested (and related) data directly. Best way to do this is a good-old rdbms + server app
4) Moving more logic from servers to clients forces you to be more careful about client versions, duplicate logic among different clients (iOS, Android, Web, Dashboard)
> 4) Moving more logic from servers to clients forces you to be more careful [...]
Back to the very old architecture of client-server-database instead of client-database that was proven dumb long time ago. The client-server-database architecture was happily ditched by the crowd that builds dynamic websites and calls them "web applications", so now everybody rediscovers that it actually is a poor idea for client to talk to database directly.
I'm personally thankful the nosql hype has finally subsided, and everyone recognizes it for what it is, a tool in the box. Not everyone has made that realization yet, as other posts in this thread indicate.
Server pushing data enables some really useful things, the archetypical example being online chat. Adminless backends are also very attractive to a lot of people, in particular front end devs who just want to build, not do a poor (insecure) job admining servers. I personally lament this "everyone's a server admin" culture we have come into in recent years.
But those innovations aren't enough to make up for the deficits the author, and many here are describing. Like others have said, use Firebase for what it's intended, and when you really need to scale, be prepared to roll your own solution.
"You need to ask a Google person to scale further, but hey we're Google and we do everything we possibly can to avoid human contact." Bleh.
What? I use claims in JWT with firebase and it works like a charm.
``` ".read": "auth != null && (root.child('users').child(auth.uid).child('claims').child('isAdmin').val() == true)", ```
This security rule will lets users read data only if their account is present in `users` collection and has `claims.isAdmin == true`. I did not test the above snippet but I have something very similar working in a project already.
https://stackoverflow.com/questions/38423277/does-firebase-c...
I implemented the solution in a Firebase wrapper and it works great.
Anyway, Google is solving this in JS by implementing persistence.
Here's my response to some of your points
Only easy if you implement FirebaseAuthUI, which has a UI that is out of context and intolerable if you care about UX. Phone verification for example (albeit free, requires ugly ReCaptcha) and the AccountChooser (albeit great concept) opens in a completely Google design.
To me this is a completely acceptable security requirement. IIRC the account chooser has other related elements including accepting permissions and TBH I think there's good reason that there's a standard UX for auth stuff. It is a lot easier to just tell people, "Only trust things on google.ca, and the UI should look like Google too", etc.
Social plugins change all the time and to use the most up to date (like this awesome “Continue as {{Name}}” button) you have to implement the providers’ own JavaScript and other necessities and do a lot of work to make them work together.
You have to do this using Web too. Firebase doesn't make it harder.
You can’t easily add claims (groups, roles, feature toggles, etc.) to user’s json web token, meaning you have to create and supplement each authentication with a call to the Real-time database.
I actually like this feature request. I see it more like something that Firebase could add, but if they are trying to make it fit in with their db, it is kind of an unprecedented feature afaik, so I don't really expect it.
Querying on anything beside a simple key lookup is a pain in the bum. Somewhere, someone understands how indexing, pagination and multi-filtering works but I’ve given up. Don’t forget you do all of this client-side (JavaScript).
Indexing happens on the server side. It's actually extremely powerful. You just have to start with the question: What data do I want to show to the user when it's done? You make the entity ids of that data the value of an object in FB. Then you set up a listener that
1. Listens to all other relevant parts of the tree in real-time 2. Does some calculation on the values it retrieves 3. Saves a new key [ computed_value : entity_id ]
Then, you simply query for the top x keys, getting your entity ids, and in your UI you just instantiate your component to load the data for the entity in its own query real-time. It is fast enough to build nice UI's, that's why people win hackathons with it.
Firebase returns data as “snapshot”, a very weird, encoded structure that is not easily iterative. You have to navigate between forEach, snapshot.key and snapshot.val() to get what you want. I thought that’s the whole point of using JSON.
Snapshots are for things like user profiles where you actually just want to get the object at the given path (i.e. want to retrieve {"name":"mluggy7"} from /users/1).
If you want to iterate things, you should be using the `on` query: https://firebase.google.com/docs/reference/js/firebase.datab...
The way it works is that it it treats an object like an array of data, where the order of the array is the order of the keys in the object. It calls your callback if data is added to the array, moved around in the array, deleted from the array, or changed (but kept in the same position). You can use these callbacks to manage some internal array state where you're holding components that are initialized with the data items.
Write errors are a pain to debug, even with debugging enabled ends up as JavaScript “permission denied” with no way knowing. You have to run your payload against the simulator to get the firebase rule line you had tripped on.
You only have to learn this once :p
There’s no easy way to cache data, especially fragments that requires high computation. Why would a call to the same unchanged node by the same user not return from cache?
Not sure what you mean by computation, and I'm not sure why you'd need caching since the protocol just sends diffs of what has changed. The real-time db is the cache. You do your computations and save them in the real-time db. You can make it O(1) to search an object in both keys and values using indices, JS doesn't even really have that data structure.
REST interface will not use the signed-in user’s credential. You have to pass it as a token (which is just weird, especially if you planned to build a simple CRUD on top of firebase serverless REST paths)
You have to have a token, the firebase API has a token too but it manages it internally. If you use a Firebase REST SDK (of which there are many for many languages) then it will probably manage the token for you and just give you API methods to call for REST functions.
Firebase-admin is ignoring your database validation rules, who’s idea is that I have no clue but it caused me much grief.
Not sure what you mean here. You might be talking about an actual issue.
Cloud functions seems cool but I haven't used it so I can't comment.
(I've talked about Firebase on HN previously, for example [1]. I started using it at Hackathons in 2013-2015)
* Any non-trivial application can explode in complexity quite quickly, even with well-designed data boundaries and code flows * The human brain is incapable of managing said complexity in any effective way * We must therefore break this complexity into consumable pieces that fit inside our heads * Which means redesigning those data boundaries and data flows, in order to make them fit in our heads, which inevitably moves the complexity around the system
RAD tools HIDE all that complexity but the moment you need to move it, you can't. So you end up having to re-implement.
I am using Firebase for an app I do not expect to ever exceed a few thousand users - it is an app for a local business that is quite popular, but limited in geographical scope. So it's a good choice.
I wouldn't pick it for larger apps whose potential growth is not so limited. I'd take the hit up front to properly build an architecture that can scale (but doesn't, at first, per Martin Fowler).
That said, the idea is similar. You subscribe and unsubscribe to data. Some callback is called when data is updated.
Your feedback is both fair and something we're diligently working to fix. In response to each of these points:
1. [Local testing only works for HTTPS]. For better or worse, our product is built in layers. There's the core Cloud Functions product and the "for Firebase" add-ons. You can already see some public changes we've made to the core Cloud Functions emulator that include some support for event-handling Cloud Functions as well as improvers in debugger support. We definitely want better "in house" support and are in the user testing stages of some generational leaps in local testability with the Firebase toolchain. You can reach me at my handle at google.com if you'd like to be considered for some of the user testing.
2. [Debugging feels like a murder mystery]. Yes, this is another thing we are working on. Cloud Functions integrates with Stackdriver Debugging[1]. There are very real issues with the integration today. TL;DR: If you have a steady stream of requests, it will work. If not, the ephemeral instances won't be alive/unthrottled long enough to fetch watchpoints. This is a huge concern to many of us within Google and we're working hard to improve the way it works.
3. [No cron jobs]. Again, a huge feature request and a high priority. You don't need to use your own machine; you can use GAE's free tier to kick off cron jobs for you[2]. Still, a more tightly integrated solution is obviously ideal and is coming.
Closing: We take these issues very seriously. I'm sorry we don't have the solution to your problems today, though all three line up with active development on the team. We are focused on delivering infrastructure required for mature apps with high volume and mission critical traffic. Keep an eye out for our product as it crosses into generally available and beyond.
[1]: https://cloud.google.com/debugger [2]: https://github.com/firebase/functions-cron
There's no free lunch. Whenever you pick a technology, understand what are the downsides. If you don't see any, then you probably don't know enough. Nosql is cool, unless you start needing transactions or database level data integrity checks ( hints : you always end up needing it at some point). Cloud hosting is cool, until you realize it's way more expensive for your needs, and that network is going to cost you a fortune. Serverless is great, but then what are you going to do to ensure business rules are exactly the same for all your clients, at all times, etc. etc.
Here's an alternative I found: https://deepstreamhub.com/open-source/
It works really good. You will like it. Full control + easy interface. Got me started really quickly.
I think that all these SaaS/BaaS services do speed up development initially but they slow things down in the long run. I had the same issue with Amazon Elastic Transcoder (for videos) and SNS; once you need to split out different environments (development, staging, production) and then scale to support more regions and start splitting up jobs into more streams; it can get really difficult to the point that you wish you were running your own service instead.
We were using Firebase for simple read-only queries and our dataset wasn't changing much, so statically served nested JSON files/folders were a great substitute.
In case it helps anyone else out, here's the script that automated the creation of those files from a Firebase data dump: https://github.com/zackbrown/firebasic
I really don't know what they are doing, it seems they have made all the wrong decisions engineering-wise. I sincerely hope some team at Google is really busy right now rewriting everything.
Firebase is not meant to be a backend for any Web app. It is a special tool for specific problems. If you just use it without evaluating if it is a good fit for your problem then you'll certainly run into a wall.
My pain points:
Cloud functions debugger = -1.
Can't tell you how much fretting I have dealt with using async.each and some buffer overflows or some other low level Node.js error that never makes it to the debugger. And the debugger isn't a plaintext log. It's a tacky UI where each line is an element, the "logs" are 600px high, and whenever you scroll a little you lose your spot on longer JSON logs.
I also strongly, strongly dislike how easy it is to accidentally delete data from storage. That red X icon is wayyy to easy to accidentally click and daily backups only don't give you wiggle room to recover on heavily used apps. This makes it sadly difficult to use their database view to present quick things to others without building a UX for it.
Let's not talk about how setting a field to `new Date()` just loses the value entirely instead of throwing an error or defaulting to ServerTime.
I feel that Firebase has a lot of services - and one should seriously consider what you are getting for the cost too.
Firebase Authentication - Basically free. You can pay for something like Auth0 and use the Firebase Admin SDK to add Firebase Users on authentication through Auth0 then let that service be your source of truth. Alternatively, you can spin up your own auth service on a firebase function using Passport.js and, again, roll your own solution.
Firebase Hosting - Pretty solid. Nothing crazy great and nothing crazy bad. Easy to deploy and host static files to the edges.
Firebase Database - What firebase needs is a proper NoSQL, but you can get that in the Google Cloud Services. As a Real-time layer for clients, it is pretty good. Not so great if your corporation is on AWS. But, there are options (like deepstream.io) that might require a bit more setup work. How long until every cloud provider has a real-time data layer offering though? Firebase won't hold this space forever.
Firebase Functions - Now, there are a number of comparisons around the functions vs AWS, Azure, etc.. Functions are what they are and they all perform better/worse in various ways. Deploying Firebase Functions is WAY easier than spinning up Lambdas. That said, The Serverless framework makes that much easier too... Serverless actually supports many cloud providers.
If you want to have a real-time app, Firebase, Deepstream, SocketCluster, etc... None of those should probably be your "core" database anyway. They are all great data-sync solutions.
I think that people using Firebase should be aware of growth paths and if they think they will need a feature, build for it. Abstract your code so you can move away from Firebase or extend it with other services. Treat the Firebase Database as the handy real-time layer, but consider storing your data in a proper database elsewhere.
Remember, you can do a complex query in another database and then use the ID results to point the client to Firebase records to sync to (for instance). This, of course, applies to other solutions too. Heck, Deepstream provides RPC calls so you can make those queries then subscribe to your results (if you need real-time results).
Why I still use firebase has 2 major reasons. 1) Cloud Functions 2) Using Firebase-DB as my model and never query anythings from firebase. 3) I really don't want to touch docker/aws/load balancing/etc.
In my case, the client simply listens/writes to a particular model (DB-path). A cloud function will wake up, manipulate the model and falls a sleep.
That pretty much means, every view-model a user can see is pre-calculated and stored in the DB.
The second rule of Firebase is structure your data and populate it in a way that makes it simple to fetch with a simple key lookup.
> "You are forced to do everything client-side"... "including your SECRET SAUCE"
How I see it is the "static content" (which I assume is a SPA) shouldn't contain anything more than the conditional logic to decide when something should be rendered or retrieved from/ sent to the server.
If the "SECRET SAUCE" you are referring to is the conditional logic, then you shouldn't worry as this can already be derived purely from interaction with the UI.