Our great sponsors
-
trustfall
A query engine for any combination of data sources. Query your files and APIs as if they were databases!
-
SurveyJS
Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App. With SurveyJS form UI libraries, you can build and style forms in a fully-integrated drag & drop form builder, render them in your JS app, and store form submission data in any backend, inc. PHP, ASP.NET Core, and Node.js.
-
InfluxDB
Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
-
Hasura
Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
-
edgedb
A graph-relational database with declarative schema, built-in migration system, and a next-generation query language
-
WorkOS
The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.
If you want to see what a GraphQL with an algebra could look like, I built one! The query language is parsed with a vanilla GraphQL parser, but has directives like `@filter, @recurse, @optional` etc.
10min talk video: https://www.hytradboi.com/2022/how-to-query-almost-everythin...
GitHub: https://github.com/obi1kenobi/trustfall
> Checkout Relay.js: https://relay.dev/
Relay is a GraphQL client. That's the irrelevant side of caching, because that can be trivially implemented by an intern, specially given GraphQL's official copout of caching based on primary keys [1], and doesn't have any meaningful impact on the client's resources.
The relevant side of caching is server-side caching: the bits of your system that allow it to fulfill results while skipping the expensive bits, like having to hit the database.
[1] https://graphql.org/learn/caching/
I feel like the original Twitter thread misses some common points. Bad API design is possible with any API style. A complex aggregation with nested joins is possible with any kind of API as transport. Also they don't mention tools like Relay, which indicates that they have never used GraphQL to its full extend. We've been working a lot in this space to improve the developer experience of GraphQL, giving devs the benefits of dynamic GraphQL operations but combining it with a REST API/JSON RPC as a facade and therefore dealing with a lot of the downsides. Please check our https://wundergraph.com/ if you're interested. In terms of security, there's frameworks like entgo (https://entgo.io) that handle auth extremely well. If you look closely into the docs, you'll realize that entgo supports REST, gRPC and GraphQL as external interface. So it's clear to say that you have to deal with authz, no matter what API style. Regarding "unpredictable" performance, I'm not sure I agree with the points being made. With GraphQL, it obviously gets very visible when you have "slow queries". If an API consumer would do the same "queries" through a REST API, it might be the case that they create even more server load because it takes more requests. The difference would be that it's not really visible because you don't count 100 rest API calls as "one query". Instead, you falsely believe that you've served 100 API calls very quickly in less than 100ms each. It might be the case that the REST API calls take 10s total, while the GraphQL query took 3s. So now you're thinking that REST is 30x faster than GraphQL, but really we're comparing apples to oranges. My summary is that you should choose the right frameworks and tools for your project. REST is totally fine, but please create an Openapi specification to document it, otherwise it gets messy.
GraphQL is really useful paired with a tool like Genql [0] that creates a js library with auto completion and type safety, this makes discovering and using the API much easier and faster
[0] https://github.com/remorses/genql
Yes. It overcomplicates what can be a simple process using a bit of ingenuity and good ol' fashioned REST endpoints: https://github.com/cheatcode/joystick#customizing-outputs
/network/shortestPath?node1=<>&node2=<>
to get a list of all devices but I'm basically just writing custom Cipher code to do that query and the benefits of Neo4J basically go out the door. It still has some interesting Graph features but if all i'm doing is writing a custom endpoint for every use case it's mainly pointless.
You can do a simple POST statement which takes a Neo4J query and execute it with some caching on top of it for sure.
Either ways in order to make Neo4J worth it I need a way to make the queries more dynamic. So right now I'm thinking of:
- restQL http://restql.b2w.io/
- GraphQL https://graphql.org/
Or just having a dumb POST /custom/query that maybe only supports read operations. You can add a layer of auth but I'm not a big fan of just having some endpoint that's basically a Pipe to Neo4j. It feels just as bad as saying, typing any SQL here and we'll execute it on the server. If people know what they're doing that's fine..but at that point just setup phpMyAdmin/ pgAdmin. At that point you're trusting folks to know what they're doing and if folks accidently drop Bobby Tables (https://xkcd.com/327/) then it's an accepted risk.
If you just have a proxy to run any Cipher query, you might as well just provide users on Neo4J web instance and let them play there.
Anyways, still in early stages trying to figure out how to best leverage Neo4J
You have to do your own optimiser to avoid, for instance, the N+1 query problem. (Just Google that, plenty of explanations around.) Many GraphQL frameworks have a “naive” subquery implementation that performs N individual subqueries. You either have to override this for each parent/child pairing, or bolt something on the back to delay all the “SELECT * FROM tbl_subquery WHERE id = ?” operations and convert them into one “… WHERE id IN (…)”. Sounds like a great use of your time.
In the end you might think to yourself “why am I doing this, when my SQL database already has query optimisation?”. And it’s a fair question, you are onto it. Try one of those auto-GraphQL things instead. EdgeDB (https://edgedb.com) does it as we speak, runs atop Postgres. Save yourself the enormous effort if you’re only building a GraphQL API for a single RBDMS, and not as a façade for a cluster of microservices and databases and external requests.
Or just nod to your boss and go back to what being a backend developer has always meant: laboriously building by hand completely ad hoc JSON versions of SQL RBDMS schemas, each terribly unhappy in its own way. In no way does doing it manually but presenting GraphQL deviate from this Sisyphean tradition.
I read in the article that NOT having GraphQL exactly match your DB schema is a best practice. My response is “did a backend developer write this?”
I just got done doing a talk on GraphQL for PyCon2022 and I do agree with some of the points here. Performance work can be tedious and is not bi-directional in the graph so the number of dataloaders can blow up making debugging hard. Identifying where n+1 queries are in the API can also be difficult, but I used this open source package to help: https://github.com/tatari-tv/query-counter. I think the article failed to mention two of the things that GraphQL does really well: dense queries and built-in pagination. You're able to do the work of many serialized REST queries in one query using the node context of the GraphQL graph structure, which is a huge win if you're hitting performance issues related to requests per second to your API. Also pagination using the cursor, before/after, etc. is very helpful and Flask_Graphene enables some slick caching there to make subsequent queries at that cursor to be extremely performant. I have code with my sample implementation which simple, but shows the power of DataLoaders: https://github.com/lame/pycon-graphql.
I just got done doing a talk on GraphQL for PyCon2022 and I do agree with some of the points here. Performance work can be tedious and is not bi-directional in the graph so the number of dataloaders can blow up making debugging hard. Identifying where n+1 queries are in the API can also be difficult, but I used this open source package to help: https://github.com/tatari-tv/query-counter. I think the article failed to mention two of the things that GraphQL does really well: dense queries and built-in pagination. You're able to do the work of many serialized REST queries in one query using the node context of the GraphQL graph structure, which is a huge win if you're hitting performance issues related to requests per second to your API. Also pagination using the cursor, before/after, etc. is very helpful and Flask_Graphene enables some slick caching there to make subsequent queries at that cursor to be extremely performant. I have code with my sample implementation which simple, but shows the power of DataLoaders: https://github.com/lame/pycon-graphql.
https://github.com/tandg-digital/objection-filter
Out of curiosity, would functionality like this implemented in graphql solve your issues?
Here's the code: https://github.com/RedShift1/graphql-cached-get
Note that I made a very primitive implementation. Depending on which GraphQL node is queried, the request will be cached by the proxy or not. Apollo GraphQL server has much more fine grained methods of allowing caching (see https://www.apollographql.com/docs/apollo-server/performance...) however I left the example code crude so you see exactly what's going on under the hood.