redwoodjs / redwood

The App Framework for Startups
https://redwoodjs.com
MIT License
17.35k stars 999 forks source link

Add scaffold support for DataLoader batching #529

Open chris-hailstorm opened 4 years ago

chris-hailstorm commented 4 years ago

OBSERVATION

Redwood does a great job managing single GraphQL requests on a query --> service --> DB path. However in a more complex component, or a screen comprised of many components, the single request approach isn't efficient. Especially with many small components (each with its own GraphQL queries), loading a page could require dozens or hundreds of round-trips from the client to the backend, which can feel slow to the user (leads to a lot of "Loading" suspense displays), and require a lot of resource on the server side both at the GraphQL layer (because HTTP connections are expensive) and the database level (many redundant queries + database connections are expensive + whatever Prisma client overhead is required for each query).

An app of this kind could require 10-100x the server resources a tailored approach would use. This is not an issue for toy applications, but is a serious issue for real, scaled applications.

These problems are often not noticeable in dev environments. Unless you do volume / load testing, you won't perceive the end-user slowness nor the server resource demand. But when you move into production with significant data and number of users, you'll see the problems.

Problem overview: https://www.youtube.com/watch?v=ld2_AS4l19g

SUGGESTION

Consider adding support for DataLoader batching. This puts a layer of query batching / lazy loading between the GraphQL query and the Redwood service that delays loading to the next Node.js tick in order to aggregate / rationalize / greatly reduce the number of queries.

A visualization: https://medium.com/@__xuorig__/the-graphql-dataloader-pattern-visualized-3064a00f319f

Deep dive from the DataLoader developer: https://www.youtube.com/watch?v=OQTnXNCDywA&feature=youtu.be&t=1323

NOTE

This could be adopted in phases. The DataLoader services can exist alongside of / or build on top of the existing non-optimized APIs. The dev can decide if or when to switch to DataLoader.

You could make DataLoader part of the normal scaffold generation, or it could be an option. The scaffolded CRUD screens Redwood provides aren't complex enough to need the loader.

mojombo commented 4 years ago

I haven't confirmed this, but I believe that Prisma has some DataLoader stuff built in to solve the N+1 problem. It's something we've talked with them about before, and I know they hope to solve it without user intervention (as much as possible).

chris-hailstorm commented 4 years ago

Doing that in the Prisma layer makes a lot of sense. Most of the examples around the web are for GraphQL, but this kind of optimization only makes sense within the confines of a single DB (query optimization & caching), so I don't think there's anything to gain by doing at the GraphQL level.

thedavidprice commented 4 years ago

Hard to get visibility on the Prisma side as to current status. Here are the related, open Issues I could find:

thebiglabasky commented 4 years ago

Here is another one where the bulk of the discussion happened

pantharshit00 commented 4 years ago

We indeed batch related fineOne calls now. You can watch this talk if you want see the details of how that works: https://www.youtube.com/watch?v=7oMfBGEdwsc