6 ms·
The biggest problem with graphql is that you have to do a lot of non-obvious work to harden your system against DOS attacks or people that want to fly by and do
by stickfigure 4y ago
The biggest problem with graphql is that you have to do a lot of non-obvious work to harden your system against DOS attacks or people that want to fly by and download your whole database. It's easy to construct a query which puts unreasonable load on your system.
The more fine-grained nature of boring REST calls makes it more easy to control client impact on the system.
If you want to see the kind of work you actually need to put in to make a graphql API, look at Shopify. They have rate limits based on quantity of data returned. Cursors and pagination. The schema is a huge ugly mess with extra layers that never show up in the pretty examples of GraphQL on the internet.
Note that even if you use graphql for a private api to your web client, folks will reverse engineer it and use it for their own purposes. There are no private apis on the web.
I'm not a fan of graphql for anything that the public could see. It's somewhat akin to exposing a SQL interface; it opens up too many avenues of trouble. Keep public communication channels as dumb as possible.
- humbleMouse 4y agoThat’s exactly what it is, a made up sql layer over sql exposing a special port. Ridiculous.
- SnowHill9902 4y ago> It's easy to construct a query which puts unreasonable load on your system. Can you give an example?
- pdpi 4y agoDetails will depend on your schema, but the moral equivalent of “SELECT * FROM master_table” is a good start.
- withinboredom 4y agoHave you seen the “turn your database into a graphql schema” products? I shudder at the poor souls who used those products. I mean, I assume they are decent products, but man, it’s got to be so easy to screw it up and literally expose too much…
- throwawaymaths 4y agoHasura seems to be fine which we use internally in our company, though to be honest I don't do any complex queries and I don't think anyone is doing aggressively nested joins.
- acdha 4y agoI think that can be part of the problem: if you use it for a few things which make sense, you get used to it and everyone thinks it's pretty solid after a while and probably starts using and likely exposing it in other areas. Then you get someone new writing different code or a clever attacker and it turns out there was a lot of room to expose unintended data or create performance issues.
- throwawaymaths 4y agoI don't think hasura allows unbounded queries by default? I'm not 100% sure though, I didn't set it up at where I work.
- stickfigure 4y agoIt's actually worse than that, because with graphql you can create a single query which is the moral equivalent of: SELECT * FROM master_table LEFT JOIN sub_table LEFT JOIN sub_sub_table LEFT_JOIN sub_sub_sub_table... ...which is effectively "dump everything". In a REST environment you'll at least need a lot more individual requests - that's both the blessing and curse.
- lazyasciiart 4y agohttps://payatu.com/blog/manmeet/graphql-exploitation-part-4 https://payatu.com/blog/manmeet/graphql-exploitation-part-4 query dos { allDogs(onlyFree: false, limit: 1000000) { id veterinary { id dogs { id veterinary { id dogs { id veterinary { id dogs { .....
- thr0wawayf00 4y agoIt's also not that hard to implement attribute filtering with REST endpoints. People make a big deal about being able to control the shape of your API responses with GraphQL, but this completely achievable with standard REST APIs as well.
- tshaddox 4y agoSure, you could have a syntax for requesting (potentially recursive) nested resources in the query string of a REST API, and there are some systems that do something close [0], but if you do it’s probably a less friendly syntax than GraphQL and has all the same problems as GraphQL regarding performance and rate limiting. [0] A very simple convention for including nested resources in a JSON API: https://www.jsonapi.net/usage/reading/including-relationships.html https://www.jsonapi.net/usage/reading/including-relationship... A totally cool but kinda over the top library that exposes a REST API over your database with a very GraphQLesque query string syntax that supports recursively nested resource inclusion, filtering, etc.: https://postgrest.org/en/stable/api.html#nested-embedding https://postgrest.org/en/stable/api.html#nested-embedding
- ryanbrunner 4y ago99% of the time you don't need to be recursive though. Field filtering with 1 level of expansion for related resources solves 95% of problems for you, and if you're implementing something on your own API, you can have a custom route for the 5%. GraphQL falls into the same trap that a lot of things do IMO - it assumes that because 5% of things are complex, that you need a solution that can deal with that complexity for 100% of your API, which needlessly complicates everything else.
- ec109685 4y agoAgree with this. We created our own nested query language using matrix params and path separators to let the client query for nested sub-resources, including filters against collections. It’s pretty neat but nice graphql standardized it so things like consoles and other tools can be written against it.
- 4y ago
- pan69 4y ago> Note that even if you use graphql for a private api to your web client, folks will reverse engineer it and use it for their own purposes. There are no private apis on the web. How is this a GraphQL specific problem?
- crabmusket 4y agoIt's not, but the OP is saying this to pre-empt the "just use GraphQL for private APIs" defence.
- agucova 4y agoAt least compared to classical REST, usually access is limited to whatever the programmer explicitly chose to add, instead of being open by default.
- Aeolun 4y agoThat’s weird. You explicitly choose what to add to your GraphQL API too. If you’re just setting up a random library that exposes your entire database, that’s no fault of GraphQL.
- mbfg 4y agoI think it's a marketing problem. GraphQL can easily sound like "Give the entire schema to your users and let them decide what to query for". If you look at various GraphQL supportive websites, that is a common anthem. You don't get that marketing from REST. REST says "decide what's good for them". Obviously you can do either in either. But i definitely think the marketing is world's apart. So when people come to a problem, if they are not super strong in their understanding of what will be a good solution, they generally implement what the platform markets.
- dhritzkiv 4y agoYeah, I caught that too. A lot of comments sounds like they're relying on Prisma/Husara/etc. to map directly to the database. I'm sure it's fine for some use cases (such as when prototyping), but I prefer to design and build out GraphQL APIs with a more UI/product-centric approach, which hide most of the database details.
- softfalcon 4y agoWe avoid this by statically analyzing the queries that are used by the client, generating id’ed persisted queries for them, and only allowing those to be run if you’re un-authenticated/a regular user. We also have user roles, which, if you’re an admin, you can run raw queries of whatever you want, but basic users are locked to the persisted query options. It’s pretty cool, definitely adds complexity to our builds/permissions, but it works. We rolled our own, but I think Apollo GraphQL supports this out of the box now. Not saying people should use GraphQL for everything though. It’s kind of overkill for a lot of apps.
- PragmaticPulp 4y ago> We avoid this by statically analyzing the queries that are used by the client, generating id’ed persisted queries for them, and only allowing those to be run if you’re un-authenticated/a regular user. I worked with a team that was going down a similar path. At some point it felt like they were reinventing REST on top of GraphQL with a strict set of predefined queries and result shapes. They hadn't gone too deep into GraphQL tooling so we just switched to REST and implemented those predefined queries. Had a separate, developer-only GraphQL endpoint for prototyping things for a while, but the production stuff was easier to just build out as plain old REST.
- softfalcon 4y agoOne of the objectives of GraphQL is to replace REST, so yes, you’re right, it’s re-inventing REST. I’m not going to argue whether one is better than the other implementation wise. That’s purely personal preference. GraphQL has one super power though. I have access to an API directly and can save bandwidth by only querying and returning what I explicitly want in the data. That plus the allowed query rules stuff comes free in Apollo GraphQL now. At scale, this is huge for our bandwidth cost savings. A second big win is federation of many GraphQL schemas under one giant god schema. This is useful when you are a big company, merging two architectures with different API’s together under one umbrella. You can define the mappings from the child schemas to the god schema in another spec that has no code, just a federation schema. Again, you can do this in REST too with layered API’s, but GraphQL arguably makes it somewhat easier to do this with just config files. I also find that out of the box, the type safety guarantees of GraphQL are a lot cleaner/batteries include than the REST work I did the many years prior. It’s all do-able with either tech and you are correct in feeling like it’s re-inventing the wheel. It is, and that’s purely a business decision to make money pivoting devs to a new library/environment. I won’t judge you for wanting to stick with REST. It’s tried and true methods that will work for many many use cases. To each their own!
- wallfacer120 4y agoHow could someone reverse engineer anything other than your data model from gql queries?
- ewittern 4y agoWe did research on solving the DOS issue using static analysis at IBM (cf. https://arxiv.org/pdf/2009.05632.pdf https://arxiv.org/pdf/2009.05632.pdf). Our findings were that static analysis allows to determine (relatively strict) upper bounds on query complexity, which we assessed for two production GraphQL APIs (GitHub and Yelp). However, the static analysis requires some configuration to determine the (maximum) size of lists. I was later involved in productising said research into an API gateway (called DataPower) offered by IBM. We implemented our GraphQL static analysis in a quite flexible and performant way (all of GraphQL's query validation and the static analysis are implemented in C++). The required configuration for the static analysis can be provided using GraphQL schema directives (cf. https://ibm.github.io/graphql-specs/cost-spec.html https://ibm.github.io/graphql-specs/cost-spec.html). Unfortunately, DataPower is quite inaccessible to the common developer. I find that persisted queries are a very interesting approach to also solve this issue. They still grant developers the full flexibility to define queries during development, but then require providers to validate and vet queries only once before persisting them (instead of validating and vetting queries on every request). This has huge benefits for runtime performance, of course.
- deleted 4y ago[deleted]
- lfauve 4y agoThis approach builds on the persisted queries approach: https://docs.wundergraph.com/docs/features/graphql-to-json-rpc-compiler https://docs.wundergraph.com/docs/features/graphql-to-json-r... It gives you all the benefits of GraphQL during development while in production you’re only dealing with JSON-RPC
- jensneuse 4y agoWe solved this by turning GraphQL into a compile time problem and replacing it with JSON-RPC as the transport, keeping GraphQL entirely hidden on the server. It's not just great for security and performance reasons, but also comes with a lot of other benefits, like you can inject claims into Operations. Here's some more info: https://docs.wundergraph.com/docs/features/graphql-to-json-rpc-compiler https://docs.wundergraph.com/docs/features/graphql-to-json-r...