Prisma 1 Forum

Help Understanding Prisma Client's Value Proposition

I am also confused about this. We have been exploring microservice architecture with prisma, creating small, dedicated server instances for handling specific tasks. So far, we have been using a combination of bindings and delegation to expose a number these through an application-specific gateway server. I dont see how how prisma client fits in in this setup at all.

Prisma client seems like a “quick and dirty” way to access my database on an application level, but for a robust graphql backend, I dont see the advantage of the client over the bindings. The only explanation/advantage I see is that it detaches prisma from graphql, but I thought we all agreed that graphql is the holy grail :tada:

Could someone outline what role the client is to play in the future? Should it replace the binding/ delegation approach, should it offer an alternative, or does it aim to expose prisma to the consumer application in a sort of RPC style approach (Not technically, but use-wise) ?

Love to hear some thoughts! Regards!

1 Like

Seeing as all the Prisma examples have been updated to use Prisma Client in the last few weeks, and looking at the documentation, it looks like Prisma Client is intended to replace Prisma Bindings.

As with Graphcool / Prisma, the dev team will likely not say up front that this is the case, but it seems clear.

I did manage to migrate my WIP prisma app today without too much trouble anyway. Prisma Client is fairly similar anyway but the new chained methods offer some convenience.

1 Like

An aspect that I am noticing is that you cannot query relation fields of objects that are returned in a list? So, I cannot query users and return all their blogPosts as an example?

14%20PM

This seems to go in line with the above comments. Prisma bindings may be more powerful for returning data, but Prisma Client with its fluentAPI a bit easier to write queries?

I wish the Prisma team would comment on these concerns and/or outline a roadmap for Prisma Client. They need to publish a roadmap so there is some transparency.

1 Like

@BrentFarese Note that with the above example, instead of .users().links() you can pass a fragment to .users() if you want to retrieve lists server-side or use the $delegate method.

However, if you wanted to return the links list with the user type from your graphql api you can do that with a user resolver:

links: (root, args, ctx) => ctx.db.user({ id: root.id }).links()

Prisma Client is simply more flexible than Bindings.

FYI: They removed the $delegate method from the Prisma Client, the official examples use prisma-binding for schema delegation.

My biggest concern with the Prisma Client: How do you limit the retrieved fields based on the original query? Let’s say I want to retrieve something like this:

query UsersWithLinkIds {
  id
  name
  links {
    id
  }
}

If Link is a big type with lots of fields, it’s not very efficient to retrieve everything from the DB if the client only needs the ids. But how do you know what needs to be retrieved without the info object? You have to write a separate Query (with different hard-coded fragments) for every situation, which is almost the same as creating API endpoints. It removes the biggest benefit of having a GraphQL server.

Hi @kratam, thanks for your thoughts and perspective.

I normally don’t consider database overfetching to be a performance issue, but in the world of AWS, I understand that RDS charges by the output. For those more savvy in AWS/RDS land, is fetching 20 fields instead of 3 a real cost concern?

You don’t. There’s a great use case for both. I think of Prisma Client for server data – when the application needs data for some business logic. Then, bindings are for returning a subset of your Prisma data layer.

I’m not saying I can’t think of a place for Prisma Client, I just don’t understand why they want to replace prisma-binding. They solve different problems. Maybe this is no longer the case (the examples are using prisma-binding again), but I fear the devs are moving so fast I can find myself left behind with an unmaintained lib.

No one said they’re replacing it. It’s a dual track, and Prisma uses a lot of bindings internally. I suspect the dual track will be the long term solution.

EDIT: Actually, it was said. My mistake. Read below.

This is a bit my concern as well. I am not using Prisma Client and am using bindings and I do not want to be left behind with an unmaintained library. The Prisma folks should communicate the roadmap.

I think that, because prisma-binding is missing from the 1.17-beta documentation, it feels like it’s been replaced. Even if that isn’t the case.

1 Like

They actually do call it a prisma-binding replacement which is where I was most confused.

… I stand corrected. Thank you for bringing that up @HenrySipp . In speaking with Prisma, they suggested a dual track, but the article does indeed say replacement.

Would be great if we could get an official response in here that elaborates on the future of prisma-binding.

I don’t think any of us mind the existence of the client - perhaps the Prisma team simply feel like they’ve reached the limit of what features can actually be added to prisma-binding, and just want to offer a second option for less robust APIs, which would be totally cool - but clarity, in the form of a roadmap or something else, would be nice.

I tried the client in my actual GraphQL server, and it was significantly weaker than schema delegation for all but the most simple of queries, so the notion that it’s replacing it, as the article implies, is worriesome.

3 Likes

Hey everyone :wave: first of all, thank you so much for your great feedback, questions and thoughts! We apologize for the confusion as well as for the delayed response. In this post, we want to reply to the concerns and questions that were raised previously in this thread.

On a demo project, the additional resolvers are non-trivial. On a real production application, it’s resolver mania. @Lawjolla

It is true that the client requires you to implement type resolvers for types that have relations to other types. Note that @Mark_Petty’s comment is very much in line with our thinking that resolvers can be auto-generated (using graphql-resolver-codegen ) to save writing boilerplate code. If your application schema is very similar to your Prisma GraphQL schema, schema delegation and Prisma bindings might be a great fit for your use case as well. (Note that you can also combine using the Prisma client and bindings in the same application.)

is it actually required to define all our graphql types and resolvers independently of the service @Findiglay

It is not a hard technical requirement to define GraphQL types independently of your Prisma service but we highly recommend to do so. The Prisma client is best to use it when your Prisma GraphQL schema should be decoupled from your application schema. In these cases, you have more control over the application layer by redefining the types in the application schema. If your application schema is very similar to the Prisma GraphQL schema, the more suitable approach might be to using Prisma bindings (i.e. schema delegation) with graphql-import .

Should it replace the binding/ delegation approach , should it offer an alternative, or does it aim to expose prisma to the consumer application in a sort of RPC style approach (Not technically, but use-wise) @Moritz

The Prisma client is intended to be an alternative to Prisma bindings and it is perfectly fine to use them together in the same application. As was mentioned by @kratam, $delegate has been removed from the Prisma client API to make the use cases for both approaches more clear:

  • Prisma client: Simple, and flexible API with convenient method chaining but without schema delegation but with full type-safety
  • Prisma bindings: Main use case is implementing a GraphQL server with schema delegation based on the resolvers’ info argument

The prisma-binding package will not be deprecated and can, of course, be used in production applications in the future!

(Side-note: We apologize for the confusion we caused through the wording in the beta announcement blog post. We updated "The Prisma client […] replaces Prisma bindings as a way to access data in your applications." to "The Prisma client […] can be used as an alternative to Prisma bindings as a way to access data in your applications")

An aspect that I am noticing is that you cannot query relation fields of objects that are returned in a list? So, I cannot query users and return all their blogPosts as an example? @Lawjolla

As @Kratam pointed out correctly, it is possible to retrieve relations by using the $fragment API. You can of course also use $graphql directly. Also note that we’re working on an API design that will make this possible in the future (more info here).

it’s not very efficient to retrieve everything from the DB if the client only needs the ids @kratam

This can also be solved using the $fragment API.


By removing $delegate from the Prisma client, we’re making a clear distinction between the Prisma client and Prisma bindings.

Prisma bindings have schema delegation as their core feature and thus serve a very specific use case: Building GraphQL servers where the application schema is very similar (and should be strongly coupled) to the Prisma GraphQL schema.

Prisma client serves a more general purpose with a more flexible API. It can be used beyond the use case of building GraphQL servers and also might be the better tool when application schema and the Prisma GraphQL schema should be largely decoupled. Finally, a very important aspect are entirely type-safe resolvers which is extremely complex to achieve with schema delegation but really simple with the Prisma client (and a tool like graphqlgen).

Another reason for removing schema delegation functionality from the Prisma client was because we wanted the API / feature set of the Prisma client to be consistent across languages, but schema delegation only exists in the JS ecosystem.


We also apologize for the lack of examples and documentation. We’re working hard on improving that :pray:

EDIT: A number of examples for using the Prisma client can be found here. To learn how to build GraphQL servers with the Prisma client, check out this tutorial on How to GraphQL.

14 Likes

Thanks @nikolas for your response, this clears up a lot. I have one more question: Is it possible or even intended to use the generated prisma client as a data provider in a client application consuming the prisma api? We though about importing the backend schema containing the types into a react client and generating the prisma client there for direct usage as a data provider. Is this design feasible? Are you planning on adding apollo client features like caching and custom headers to the client or is it intended to just be a light, cross language layer on top of the bindings? I feel like for any server following opencrud conventions, the prisma client could be a nice way to access the backend from the frontend. Thanks!
:champagne:

Hey Moritz, glad the post brought some clarity. Regarding your questions:

Is it possible or even intended to use the generated prisma client as a data provider in a client (i.e. frontend) application consuming the prisma api?

It is possible to use Prisma client directly in your frontend app but this is not quite the intended architecture. If you don’t put an API server in between your Prisma API and your React frontend with a Prisma client, it basically means your entire database is exposed directly to the frontend and there are no means to add features like authentication, authorization or implement any sort of business logic. This is typically not want you want in a production application.

Are you planning on adding apollo client features like caching and custom headers to the client or is it intended to just be a light, cross language layer on top of the bindings?

We’re currently not planning to add such features to Prisma client. Apollo Client and Prisma client are very different:

  • Apollo Client is a general purpose GraphQL client with view-layer integrations that’s used in frontend app
  • Prisma client is prisma-specific and auto-generated library that’s primarily used in your application server (replacing traditional ORMs) to access a Prisma API. Its main purpose is to provide a simple way to access the Prisma API from code, think of it more like a “Prisma SDK”. So it would indeed rather be the " light, cross language layer".

I feel like for any server following opencrud conventions, the prisma client could be a nice way to access the backend from the frontend.

This is actually an interesting thought that we haven’t discussed internally yet but that surely is some great food for thought. Thanks a lot for pointing that out! :pray:

1 Like

Thanks for your quick response!

This is actually not the case, as long as the middleman server (in our case mostly yoga-based) implementing the business logic follows the prisma/opencrud conventions. We played around with it a little and the client does not seem to care what happens behind the resolvers as long as they follow the conventions. The only problem is that permissions are tedious since it is currently difficult to add authentication to the headers.
We actually found it a great way to expose the prisma crud to our client with a business yoga layer in front of the db. Assuming that adding auth headers to the client should be easily implemented (I would love this feature for our microservice setup anyway btw :slight_smile: ), caching is the only issue. For building admin-interfaces, only accessing a portion of prisma crud, this seems like an awesome out of the box solution to me.

Ah sorry, I then misunderstood your questions. I wasn’t aware that you do have your yoga-based API server in that setup and basically just use it to mirror the Prisma CRUD API! In that case I think using the client in the frontend should be perfectly fine! As for the caching, I’m not quite sure if this is smth that we’re going to build any time soon since (as I said) the client is not really intended to be used directly in the frontend. However, adding further headers to the client indeed doesn’t seem like a super difficult feature, do you mind creating a feature request for it so we can pursue this further? (Also definitely feel free to create a FR for caching functionality in the client so it can be “officially” debated.)

By removing prisma.$delegate, when I upgrade from current prisma 1.17.0-beta.2, my application gets broken. What’s recommended course of action in this regard?

import { GraphQLServer } from "graphql-yoga";
import { ApolloEngine } from "apollo-engine";
import { Prisma } from "./generated/prisma-client-js/index";
import compression from "compression";
import { resolvers } from "./resolvers";
import { RequireAuthDirective } from "./directives";

const prisma = new Prisma({
  endpoint: process.env.PRISMA_ENDPOINT, // the endpoint of the Prisma API (value set in `.env`)
  debug: true, // log all GraphQL queries & mutations sent to the Prisma API
  secret: process.env.PRISMA_SECRET
});

const server = new GraphQLServer({
  typeDefs: "./src/schema.graphql",
  resolvers,
  schemaDirectives: {
    requireAuth: RequireAuthDirective
  },
  context: req => ({
    ...req,
    db: prisma.$delegate
  })
});

// Enable gzip compression
// ref: https://www.apollographql.com/docs/engine/setup-node.html#enabling-compression
server.express.use(compression());

const port = parseInt(process.env.PORT, 10) || 4000;
if (process.env.APOLLO_ENGINE_API) {
  const engine = new ApolloEngine({
    apiKey: process.env.APOLLO_ENGINE_API
  });

  const httpServer = server.createHttpServer({
    tracing: true,
    cacheControl: true
  });

  engine.listen(
    {
      port,
      httpServer,
      graphqlPaths: ["/"]
    },
    () =>
      console.log(
        `Server with Apollo Engine is running on http://localhost:${port}`
      )
  );
} else {
  server.start(
    {
      port
    },
    () => console.log(`Server is running on http://localhost:${port}`)
  );
}
1 Like

This topic was automatically closed 45 days after the last reply. New replies are no longer allowed.