nexus icon indicating copy to clipboard operation
nexus copied to clipboard

Apollo Federation support

Open jferrettiboke opened this issue 5 years ago • 26 comments

Apollo Federation was open sourced a few days ago by Apollo team. I would like to know if there are plans to integrate Apollo Federation into Nexus in some ways. I just pretend to discuss deeper how this would look like.

I think the way that Nexus provides to extend types is similar to what Apollo Federation does. However, Apollo Federation allows us to create a gateway from different URLs (other GraphQL servers as services) and each URL is a service running independently. I would like to discuss this with some of you guys because doing things in a similar way is easier to maintain and it's better for teams at scale.

The good thing about this is that every team can use the programming language they want (I read somewhere that Apollo plans to expand to other programming languages), and using the gateway in Apollo Federation, all URLs can be merged at once easily and clients will see all graphs connected. Think this like a microservices pattern for GraphQL services.

Nexus is great, but if we try to implement everything within the same server, it will not provide freedom to teams since everything must be done in the same language because Nexus has no ways yet to connect easily to other GraphQL services. In an attempt to mitigate this, I created an issue in prisma/nexus regarding plugins, but it is still in discussion.

Also, running a solo-server using serverless is not efficient and costs are higher. We use Zeit Now and we like to split everything as much as we can so that we are pretty sure that once a function is called, it only does one thing (but very well). This scales so well. With Apollo Federation, you can have as many servers as services you have, plus the server which acts as a gateway.

I think having something like this is a big plus. We can discuss this as much as you want, guys. I would be more than happy to contribute to the future and success of Nexus.

jferrettiboke avatar Jun 01 '19 16:06 jferrettiboke

Not yet, but I am interested in taking a look and seeing what the opportunity for integration might be here - been on vacation the last week or so, so I'm just getting caught up, haven't had a chance to take a look at the specifics of how Apollo Federation is spec'ed to work.

I created an issue in prisma/nexus regarding plugins, but it is still in discussion.

Interested to see what you think of the changes merged in #143 and if it'll address anything you're looking to do re: plugins

tgriesser avatar Jun 03 '19 00:06 tgriesser

After reading through the current Federation spec I think there is a great opportunity to build additional functionality on top of nexus to adhere to the Federation spec and allow building these types of schema's.

Most of the spec is actually fairly straight forward, I think implementing the __resolveReference resolver is rather trivial. The only thing that is a little more clunky is the extra work that is needed to provide the schema with additional meta data for the federated graphs. Creating additional types on the schema (as described in the spec) is fairly doable I only dislike one detail of the spec in it's current form, which is that the _service field is a String that has to return a fully printed schema SDL with the federated directives attached at the right locations. I think this is where it gets tricky in approaches that start from code-first. In theory this is possible but it requires additional mechanisms to re-construct the schema, attached all the directives in their corresponding locations and print this schema, coming a code-first approach this is harder to do because we don't have the fully decorated original schema like an SDL-first approach.

Because I am rather interested to hear what their idea and vision is behind this printed SDL approach. Since the printed SDL is mainly used for meta data I feel there is an opportunity to put this meta data in the schema in a more conventional way which would be easier to construct in code-first approaches. Out of personal interests I opened a ticket already at apollo: https://github.com/apollographql/apollo-server/issues/2769 to discuss this.

Nayni avatar Jun 04 '19 08:06 Nayni

Any updates on this?

brafdlog avatar Sep 07 '19 19:09 brafdlog

You can add federation to you nexus schema using graphql-transform-federation. It will not give you the build time type safety that nexus does, but it does perform strict checking on startup.

Let me know what you think.

0xR avatar Oct 10 '19 14:10 0xR

Good work @0xR ! 👏 It look functional, but I think it'll be a bit awkward at scale. What do you think about the approach @tgriesser ?

jhalborg avatar Oct 21 '19 11:10 jhalborg

I agree it's awkward at scale, I see it as a temporary solution until nexus has better federation support.

However, for situations where you don't have control over your schema it is the only solution. For example a managed graphql service or generated graphql schemas.

0xR avatar Oct 21 '19 12:10 0xR

Just in case if someone wants to see it in action: https://github.com/nayaabkhan/nexus-federation-example. Hoping to evolve the example further with complex cases and finding patterns to use it at scale (e.g. having separate objects in each type and merging into a final configuration for transformSchemaFederation).

Also, something to be aware of https://github.com/0xR/graphql-transform-federation/issues/1 when using it with Nexus.

nayaabkhan avatar Nov 12 '19 09:11 nayaabkhan

I wanted to implement simple schema stitching and old way is now deprecated in favour of Federation. So with nexus the only way to use is through the https://github.com/0xR/graphql-transform-federation The example for federated schema with the gateway is ok, but I don't need a gateway, I just need to federate my schema within one server instance. So buildFederatedSchema from @apollo/federation won't work, e.g.:

buildFederatedSchema([Account, SomethingElse].map(schema => parse(printSchema(schema))))

if Account is:

export default transformSchemaFederation(schema, {
  Query: {
    extend: true
  },
  Account: {
    keyFields: ['id'],
    resolveReference(reference: any) {
      return {
        id: reference.id
      };
    }
  }
});

Because it fails to federate Query. It just weird to see that such mature Apollo moves slowely in support of other tools for building something on top of it, it's been a while since Federation was open sourced....

LexSwed avatar Nov 21 '19 09:11 LexSwed

@LexSwed

If you're just using it inside one server instance, I'd stay away from Federation as it is a tool to federate across multiple servers - it would complicate your development needlessly.

@tgriesser posted a great comment touching on this in another issue .

On another note, Apollo actually moves fairly fast if you consider how many depend on their tooling to be stable, but they do not seem keen to support a code-first approach to schemas at the moment, that's for sure. But give them a break - they actually just open sourced Federation this summer, and they probably have their plate full supporting the current first iteration before moving towards a v 2.0 😉

jhalborg avatar Nov 22 '19 07:11 jhalborg

Any update on this? The lack of federation support makes me very reluctant to choose nexus for my next project. It's sad that this federation thing is not part of GraphQL spec itself...

On one end we want a unified GraphQL API layer but on the other end it is not really adapted to large-scale applications and service-oriented architectures.

gabsn avatar Aug 25 '20 12:08 gabsn

I am still waiting on Apollo to give an update on my initial question https://github.com/apollographql/apollo-server/issues/2769 which has been open for quite a while now.

From what I can tell I don't see Apollo having any plans in their road-map to make Federation more code-first friendly. In fact it feels like they are promoting the SDL first approach more than ever and its being picked up by other languages which have been building implementation on supporting SDL first as a second option to create GraphQL services.

On the other hand I've personally come to the conclusion that Federation is only worthwhile if you are planning on designing your schema in a way that requires you to have multiple autonomous teams work on the same schema, which I see as an exception rather than the rule (even though I get that people hype this up greatly just as the more general term of microservices).

In my experience GraphQL is still delivering on the unified API layer promise and creating a great abstraction of this layer. The typical way I've built multiple API's now is that we start of as a monolith creating the schema and the implementation in a single GraphQL service. In time (as the product matures) this service starts to break down into multiple smaller services where each service is focusing more on its core domain but the exercise to get to what that domain exactly is can only be done by starting from the monolith and breaking it apart as we learn more about the product we build.

I think Federation is in this case a way to break down these services but there are other patterns too. I still think it's wrong from Apollo's perspective that since the launch of Federation the approach for Code First has been left in the dust and totally neglected but that doesn't mean there aren't other options. I've successfully broken down monoliths into smaller services using REST or gRPC as back-end services to supply the data for the unified schema. I realize that this means going back to REST (which we wanted to avoid) or in the case of gRPC introduce a new technology into the stack can be daunting but that doesn't mean you cannot solve the problem without Federation.

All that said I'm hoping that now that the field extensions feature has been merged in for a while (https://github.com/graphql/graphql-js/issues/1527) Apollo might re-consider their SDL directive parsing and put these information blobs into more Spec compliant places of the schema instead of an ugly SDL print with directives attached.

Nayni avatar Aug 25 '20 17:08 Nayni

GraphQL-Tools's schema stitching now supports type merging similar to Federation, as well as specification of merge instructions for the gateway via directives (see our docs and https://github.com/gmac/schema-stitching-handbook for examples).

We want to support specification of merge instructions via extensions for code first schemas such as Nexus. Just checking first if Nexus lets you specify extensions for types and fields, and want to inquire as to whether there is anything I should know about how you handle extensions within the framework. I imagine that we will follow supposed best practices and nest our type field extensions under a GRAPHQL_TOOLS_SCHEMA_STITCHING key... We will probably have options on the gateway to modify the location of the extensions as desired. Just inquiring whether there is any Nexus specific info about extensions that I should be aware of...

yaacovCR avatar Dec 18 '20 10:12 yaacovCR

Something in nexus akin to https://typegraphql.com/docs/extensions.html ??

See https://github.com/MichalLytek/type-graphql/issues/351#issuecomment-747999216

Thanks again!

yaacovCR avatar Dec 18 '20 10:12 yaacovCR

https://github.com/graphql-nexus/nexus/blob/main/src/definitions/objectType.ts#L160

Looks good from here!

yaacovCR avatar Dec 18 '20 10:12 yaacovCR

Decided to go a different way and follow Gatsby/graphql-compose convention of reading directives from extensions.directives -- see https://github.com/graphql/graphql-js/issues/1343#issuecomment-479871020 -- but I also allowed this to be customized as desired.

This is now released as canary, see https://github.com/ardatan/graphql-tools/pull/2391

To get this working:

  1. Add the prebuilt directives to the schema from @graphql-tools/stitching-directives
  2. Use the directives within the schema via extensions.directives
  3. Expose the SDL to the gateway via some resolver (_root, _args, _context, info) => printSchemaWithDirectives(info.schema) where printSchemaWithDirectives is an improved @graphql-tools/utils function that follows same convention as above.

For a peek at fully worked out examples of stitching with SDL-first approaches, take a look at https://github.com/gmac/schema-stitching-handbook, where @gmac takes you through step-by-step from the basics all the way to hot reloading/versioning releases.

Hopefully, soon an example will appear with code-first approach.

Thanks!

yaacovCR avatar Dec 20 '20 22:12 yaacovCR

Nexus support is live with stitching directives (in extensions):

https://github.com/yaacovCR/schema-stitching-demos/blob/code-first/code-first-schemas/services/inventory/schema.js

note that although nexus supports tagging schema entities (types, fields) with directive nodes (directive use on schema entities) via extensions, it does not seem to support adding actual directive entities (the actual definitions of custom directives).

I think this is incorrect behavior, a server might want to implement a custom directive on a query.

You can do this quite easily in graphql-js

new GraphQLSchema({
  ...
  directives: [...specifiedDirectives, ...your_array_of_custom_directives],
})

I worked around this by using extendSchema to add in more typeDefs, but see the graphql-js example where I just loaded in the actual directives. (https://github.com/yaacovCR/schema-stitching-demos/blob/code-first/code-first-schemas/services/accounts/schema.js)

yaacovCR avatar Dec 22 '20 20:12 yaacovCR

@yaacovCR Sounds awesome, would love to take a look. Was your schema-stitching-demos repo made private or removed?

coopbri avatar Feb 03 '21 03:02 coopbri

See main repo https://github.com/gmac/schema-stitching-handbook

yaacovCR avatar Feb 03 '21 07:02 yaacovCR

Awesome, thanks a lot! Super useful.

coopbri avatar Feb 03 '21 07:02 coopbri

I also made an example repo of using Schema Stitching with Nexus here: https://github.com/nayaabkhan/nexus-stitching-example.

nayaabkhan avatar Apr 11 '21 13:04 nayaabkhan

Hi, any updates on how to use Nexus with Apollo Federation? I am struggling to create the subGraph with the directives

victoriris avatar Aug 18 '21 19:08 victoriris

Its going to be easy once the PR is merged

Sytten avatar Aug 18 '21 20:08 Sytten

Any luck per victoridp's request?

scottmccaskill avatar Sep 08 '21 23:09 scottmccaskill

Any news to this?

mengqing avatar Mar 24 '22 05:03 mengqing

Another bump to any updates on federation support, heavily desired!

chav-aniket avatar Apr 04 '22 14:04 chav-aniket

Is it possible to create a similar GraphQL Federation spec? Apollo has designed a great architecture, but it seems to be blocking further progress. The community should initiate a boycott of Apollo Federation to explore alternative solutions.

andreventuravale avatar Aug 01 '23 20:08 andreventuravale