Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaces #163

Open
OlegIlyenko opened this issue Apr 10, 2016 · 112 comments
Open

Namespaces #163

OlegIlyenko opened this issue Apr 10, 2016 · 112 comments
Labels
👻 Needs Champion RFC Needs a champion to progress (See CONTRIBUTING.md) 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md)

Comments

@OlegIlyenko
Copy link
Contributor

At the moment all GraphQL types share one global namespace. This is also true for all of the fields in mutation/subscription type. It can be a concern for bigger projects which may contain several loosely-coupled parts in a GraphQL schema.

I tried to describe this feature in detail in following article (which also includes motivation and different use-cases):

GraphQL Namespaces Proposal

After posting this it, I saw interest from different people within the GraphQL community, so I decided go one step further and open this issue in order to suggest inclusion of this feature in the spec and start a discussion around it.

I suggested particular syntax & semantics for the namespaces, but I myself still not 100% sure that it can be used as-is. I hope, that as we discuss it, we would come up with better syntax and semantics (or maybe even entirely different feature) that better fits existing language features and covers described use-cases.

@He-Pin
Copy link

He-Pin commented Jun 7, 2016

I think the / syntax is great ,with the current GraphQL spec,we need mount the on GraphQL ObjectType to another bigger GraphQL object as a field and a new name,like Mount Dummy type to a bigger graph as dummyService field.

And still I think #174 have something similar,just a little namespace.

@leebyron
Copy link
Collaborator

leebyron commented Jul 2, 2016

Thanks for writing this up, Oleg!

I'm a bit confused as to what this is enabling that isn't already possible or what the immediate goal of using namespaces would be.

I also expressly want to avoid namespaces being included and then people naively namespacing everything just because the feature is there, since that would result in a lot of bloated queries.

For example, in your post you explain that we could write queries like this:

{
  person(id: 12345) {
    id
    firstName

    schema.org/parent {
      givenName
    }

    schema.org/knows {
      givenName
      taxID
    }
  }
}

but I'm curious why you would prefer that over:

{
  person(id: 12345) {
    id
    firstName

    parent {
      givenName
    }

    knows {
      givenName
      taxID
    }
  }
}

The latter seems to represent the same thing, but just requires less typing. Is the goal to just describe what the fields relate to? Perhaps we could have metadata about the fields in the introspection system?

@JeSuisNikhil
Copy link

I think that the namespaces here enable one to "import" another schema. One could potentially import an schema and build on top of that rather than starting from scratch every time. Implementation wise it looks tough to do though. It might just be easier to import a library (js, ruby, python, java depending on the graphql implementation language) and then build schema using types available from that library.

Another reason why namespaces could be useful is so one can filter a introspection query with a namespace string. In a large system the number of types can make the introspection query results quite unwieldy. But then one could always write a custom introspection query that accepted a filter on a field that's common to all types.

I can think of another use of namespace which is that the number of top level fields (especially those with parameters) and mutations can become quite unwieldy and so one would have trouble viewing them in a graphql api browser like GraphiQL. Having top level fields and mutations further filtered by a namespace would make things easier on the eye.

@OlegIlyenko
Copy link
Contributor Author

@leebyron Thanks a lot for looking into this and giving your feedback!

I think we can approach this from 3 different perspectives. First is a semantic meaning of types and fields. This is where schema.org example came from. I think for this one it should be enough to have a user-defined metadata on a field and type level which is exposed via introspection. I think community then can come up with conventions for how to encode this semantic information for use in different tools.

The second is the fact that the mutation (as well as subscription) fields share global namespace. Mutation type is the only place where mutation can be defined for a whole GraphQL schema. This is where my original motivation came from. I went into details about this particular point in the original post ("Mutation Type" section).

There are several factors to why I see it as a concern. At the moment mutation type should be an ObjectType, which means there that all mutation fields should be defined in it. This makes it hard to work with loosely-coupled parts of the schema which potentially may have name conflicts. In my opinion, one of the contributing factors is also the lack of polymorphism in input objects. This greatly limits amount of logic one can encode in one particular mutation field, which means that different variations of updates need to be represented as top-level mutation fields.

Namespaces can provide a solution for this particular problem, but I'm pretty sure that there are also other approaches we can take. For instance, let's imagine that it is possible to use a union type as a mutation type:

type AuthorMutation {
  create(firstName: String!, lastName: String!): Author
  changeName(id: String!, firstName: String!): Author
  delete(id: String!): Author
}

type ArticleMutation {
  create(title: String!, authorId: String!): Article
  changeText(id: String!, text: String): Article
  delete(id: String!): Article
}

union Mutation = AuthorMutation | ArticleMutation

schema {
  mutation: Mutation
}

a query like this would not make much sense because field name is ambiguous:

mutation {
  create(firstName: "John", lastName: "Doe") { id }
  delete(id: "1234") { id }
}

but we can use an inline fragment to disambiguate it:

mutation {
  ... on AuthorMutation { 
    create(firstName: "John", lastName: "Doe") { id }
  }

  ... on ArticleMutation { 
    delete(id: "1234") { id }
  }
}

If we provide a shorthand syntax for inline fragments, it can become a bit more cleaner:

mutation {
  AuthorMutation/create(firstName: "John", lastName: "Doe") { id }
  ArticleMutation/delete(id: "1234") { id }
}

This code violates the semantics of inline fragments and union types - they normally represent 2 mutually exclusive fields, still I use them here just to disambiguate the field names, so both mutation fields would be resolved. For the sake of example I use this approach simply because there is already syntax available for it in the language. The point I would like to make is that this example does not involve namespaces, still it addresses my issue with the global namespace for the mutation fields.

The third perspective is the the global namespace for the types. I recently had a few conversations with different people who are thinking on introducing GraphQL in their projects and companies (from small to pretty big). One question that came up several times in the discussion is whether GraphQL should serve as a facade for different internal services managed by different teams and if yes, then how does DDD fit into this picture. I do believe that GraphQL is a perfect fit for a facade API. Many client applications often have cross-cutting concerns, so it is very helpful to provide a facade for these client through a single GraphQL API, especially if clients are constrained in some ways (like mobile clients or embedded devices). On the other hand I find it helpful to think about different internal services as a bounded contexts. Each bounded context comes with it's own ubiquitous language. Given a system designed with these principles in mind, name conflicts are actually desired, but ubiquitous language within different bounded contexts can define very different semantics for the same terms (like User, Account, Product, etc.). I don't want to say that it's the best way to model system or anything like this, it's just some people use it and find it helpful for their own systems (including myself). This is where namespaces can be a very helpful tool when designing a GraphQL facade that aggregates several bounded contexts. I would be really interested to know your opinion on this topic. Do you think that GraphQL is suitable as facade in these kind of systems and if yes, then will you try to define the single model for all bounded contexts or you will try to preserve the ubiquitous language of every bounded context and minimize a common/shared area of the schema? (/cc @dschafer, @schrockn)

I also expressly want to avoid namespaces being included and then people naively namespacing everything just because the feature is there, since that would result in a lot of bloated queries.

Indeed, I do share this concern. I guess if one asks himself whether he/she needs to use namespaces, then the answer is probably no. On the other hand, as I described above, namespaces may be a useful tool to solve particular challenges (although, not the only possible tool in every given case).

The latter seems to represent the same thing, but just requires less typing. Is the goal to just describe what the fields relate to? Perhaps we could have metadata about the fields in the introspection system?

Indeed, in this particular example query I would normally skip the namespaces. This is the nice thing about the namespaces in contrast to naming conversions and other namespace emulation techniques which have quite a few disadvantages: even in presence of namespaces one can just skip them if they are not necessary (some implicit namespacing rules will apply in this case). There are also a few reasons why I may use explicit namespace in this query:

  • As you mentiond, I may use it to make it clear, for people who view this query, that this field is defined in schema.org spec and has particular semantics associated with it (best type of documentation:))
  • I anticipate change to this type in future and would like to keep my query forward-compatible
  • After some time we decided to implement schema.org interface in this type, but this cased name collisions. I will then use namespace to disambiguate the field. This is especially important in case of mutations (as i described above), where name collisions are intentional.

That said, I don't really want push concept of namespaces per se. My main goal is to address some of the issues, like global namespace for a mutations fields. Whether it is solved with namespaces or not does not really matter. I hope what I described here reveals a bit my original motivations for this proposal :)

@aschrijver
Copy link

aschrijver commented Jul 31, 2016

Hi @OlegIlyenko ,

Nice elaboration and spec you`ve written down!

In general I see a clear need for a namespaces mechanism. I am currently writing microservices that communicate using graphql. With microservices architecture each microservice represents a separate bounded context (in DDD terminology) and you can easily get type conflicts when there are many of them around. I.e. same name, different semantics, etc. Also - like you said - there will be a need for common (base) types to be defined.

Your proposal certainly has its charms, especially the notation. Yet I also have a number of reservations:

  • Additional complexity in server implementation while namespaces support could be optional
  • Less visual appealing, harder to grasp query language (visual clutter, readability)
  • It is opinionated. It offers a single way to define namespaces, while there are many existing ones around
  • You will either stay opinionated and have people stick other namespace implementations on top of their implementation, or you will have to gradually adopt all the nooks and crannies that are also in other namespaces to take care of special cases ('my namespace string has a slash', 'mine is an object, not a string', etc.).
  • It is a breaking change! Or at least it will be in environments where the server cannot dictate the query format and there are multiple spec flavours around (old and new ones)

In another issue I proposed a more general metadata mechanism, that is an extension and not breaking. See #200
The namespace could be defined in this metadata using any standard mechanism that is around (well, there should be some compatibility with JSON actually, but still).
The structure of the metadata is defined like any type and there could be introspection support with a __METADATA type.

Using this metadata proposal for namespaces, however, is far less powerful than what you propose. But it can be adjusted. What I like in this is the freedom it leaves to implementers.
Having metadata support we could wait and see how the community use it, what metadata formats are popular, before adopting a specific approach (Hell, there could be a Metadata Profiles feature in future and a 'marketplace' for profiles and other extensions. Yeah more marketplaces..)

Finally, I would be in favour of having a lean and mean base spec, and then have an extension mechanism that allows you and others to offer the kind of cool stuff you propose. It could be a standard extension. And I could consult a server to see if it supports this feature before sending my query (Note this is similar to the extension mechanism in OASIS CMIS spec and others).

Arnold Schrijver

@yarax
Copy link

yarax commented Aug 16, 2016

Just a note: I'm currently writing a wrapper around existing REST approach based on microservices (with plenty of endpoints) and namespaces are very wanted, otherwise all type names look like fact_reports_pp_campaigns_delivered

@domkm
Copy link

domkm commented Aug 23, 2016

I would also appreciate namespaces for all of the reasons stated above by @OlegIlyenko.

@leebyron Given that Facebook has nearly 10,000 types, how does it keep track of type names and query/mutation fields (which I am assuming there are hundreds if not thousands of as well)? Are there any best practices for merging schemas from multiple sources?

@xuorig
Copy link
Member

xuorig commented Nov 23, 2016

As our mutation root grows we've been asking the same questions internally.

Given that Facebook has nearly 10,000 types, how does it keep track of type names and query/mutation fields (which I am assuming there are hundreds if not thousands of as well)?

Anyway you can share alternative solutions or insight on how you've been handling that problem @leebyron 🙏 ?

@smolinari
Copy link

smolinari commented Nov 24, 2016

This might be totally off the wall and possibly even a stupid comment showing my lack of understanding, but couldn't different URLs and a routing middleware be used like namespaces? One could split up a larger app among different endpoints that way.

So, a bigger site would have

https://some-site.com/user
https://some-site.com/blog
https://some-site.com/admin

etc.

And if things are getting too involved even with this "namespacing", you could also break it down more.

https://some-site.com/user/profile (or register)
https://some-site.com/blog/page (or /gallerie)
https://some-site.com/admin/blog

I know, I know. We are heading towards something RESTy-like again with that idea, but it isn't really REST, right?

This might not solve the microservice communication issue, which I believe this idea came from. But, I think it solves the "big schema" and "name collisions" issues, since each endpoint would have its own schema. You'd also get the decoupling, which was asked for. It would allow for better asynchronicity too, because you could hit different endpoints at the same time, if needed, which I don't think would be too often. It would allow for parallelism, because breaking up into separate endpoints, theoretically, would allow a system to be scaled out much more easily later on too. And, if you refine the URLs, it isn't a breaking change.

The cons would be duplication. But really, if an app gets that big, I would imagine creating schema would be automated in some way anyway, right? Or does Facebook really have their devs go into the schema and alter or add to it all the time? I find that hard to believe.

I'm sure this blows away some other general concept that makes GraphQL so great, which I am completely missing due to my own lack of understanding. So, please do give me hell. All I can do is learn. 😄

Scott

@khamusa
Copy link

khamusa commented Jan 9, 2017

I'd like to note that allowing namespaces to be optional as long as they're unambiguous may difficult future developments of the schema, since you cannot safely add new types that would add namespace ambiguity having already allowed clients to write unnamespaced queries.

Regarding syntax, / seems an interesting choice, but I'd also propose . as a separator (in my opinion it is slightly less cluttering).

@IvanGoncharov
Copy link
Member

As @khamusa point out:

you cannot safely add new types that would add namespace ambiguity having already allowed clients to write unnamespaced queries.

So you force all consumers of your API to bloat their queries by prefixing every type and field.
I really like the idea that GraphQL force you to define a consistent vocabulary for your system.

And the biggest concern I have is that people starting to auto-generate one huge GraphQL proxy to expose a bunch of microservices without even try to reuse common types. And instead of solving communication problem in your organization you forcing your API clients to work around this by using prefixes and reading a ton of docs to understand the difference between: schema.org/Person, Accounting/Person, CRM/Person, etc.
Moreover, I imagine a lot of developers will abuse this to implement versioning and I don't want to constantly use v1, v2, v3 namespaces.

It certainly possible to do the same stuff right now by making v1_Accounting_Person but it looks ugly and not encourage by any existing GraphQL feature.

Finally, as it was pointed out previously Facebook has nearly 10,000 types without any name clash.
And I don't think many other API will ever approach this number.

@leebyron
Copy link
Collaborator

leebyron commented Jan 9, 2017

@IvanGoncharov illustrated a number of API design abuse patterns that worry me as well.

I've still yet to hear a compelling argument for why namespaces are necessary. The only argument I've heard so far is naming collision. Frankly, that's been a non-issue for us at Facebook and our schema continues to grow well over 10,000 types.

We avoid naming collisions in two ways:

  1. integration tests.

We don't allow any commit to merge into our repository that would result in a broken GraphQL schema. This test is pretty simple and fast to run, we just boot the server and if it fails to boot with a GraphQL error, we fail the test. Two types or fields on a type of the same name would cause such a failure. This kind of test ensures our master branch isn't constantly broken, and protects against name collision problems. If someone accidentally choose the same name for a new type, they can resolve the problem. Often, resolving it actually means using the existing type rather than renaming the new one. That keeps our API internally consistent and avoids duplicate information.

  1. Common naming patterns.

We have common patterns for naming things which naturally avoid collision problems. For example, mutations often follow a "verbNoun" pattern such as "likeStory" assuming that the noun is the type it operates on and your types also don't have conflicts as well, this naturally avoids conflict. I suppose with namespaces you could have written "Story/like" but that doesn't offer clients anything they didn't already have, and it might force them to handle multi-part names when reading the result. For types, we try to generalize as much as possible so that we have types shared across products. That makes future product integrations easier as well. For products that shouldn't integrate, or have similar concepts that are rightfully different, like a Facebook Event and an advertising logging Event, we alter the name to clear the ambiguity for the reader.

@mvpmvh
Copy link

mvpmvh commented Jan 16, 2017

Say I'm looking at your API in graphiql, I'm either a new fb hire or some dev looking to integrate with a part of your API. I pick 1 of your 10,000 types and I want to dig into the mutations that fall under this type. How do I, as a new hire or third-party dev, easily consume this information?

@maciejkrol
Copy link

For products that shouldn't integrate, or have similar concepts that are rightfully different, like a Facebook Event and an advertising logging Event, we alter the name to clear the ambiguity for the reader.

@leebyron How do you not end up with horrible caterpillar names like @xuorig said? I have not so very big schema and this is already a problem.

I tried to look for examples of big schemas or best practices. Nothing. Every article I could find is based on a schema with ~3 simple types. If you have anything please consider answering this question.

@leebyron
Copy link
Collaborator

Say I'm looking at your API in graphiql, I'm either a new fb hire or some dev looking to integrate with a part of your API. I pick 1 of your 10,000 types and I want to dig into the mutations that fall under this type. How do I, as a new hire or third-party dev, easily consume this information?

Typically our types do not correspond 1:1 with mutations. We typically do not have CRUD style mutations, instead we often have RPC style mutations that correspond to user events. In the cases that there is a closer relationship, the most common mutations are typically mentioned in the description of the type. For example the Story type includes a mention in it's description of the likeStory mutation, since it's a common question.

As I mentioned in the prior comment, naming conventions can help a lot. If you're looking at GraphiQL, the ideal experience is that you start typing what you expect to work and get typeaheads with helpful suggestions. In addition to this, both search in the documentation explorer, and helpful descriptions with recommendations for common mutations are all part of the strategy of providing information in the right places at the right time.

@leebyron
Copy link
Collaborator

@maciejkrol - our type system has many types, but with some clear and easy to follow naming conventions we balance between clarity, conciseness, and expandability.

The primary goal when naming things in a type system expected to expand in the future is to have clear answers for these two questions:

  1. Does this name introduce ambiguity? (e.g. if a type is called X, do you find yourself asking "what kind of X is this?")
  2. Can we imagine future expansions of this API in which this name will become too generic and therefore ambiguous? This question is much more difficult to answer, but forward-thought is always helpful when designing long-lived systems.

For example at Facebook we have a type called User, which in the beginning was clear via context that this meant a User of facebook.com. As our schema expanded, we introduced other types like InstagramUser, ThirdPartyUser, and other more specific types unique to certain circumstances or areas of the schema. Interface and Union types then help use related types together. For example, we have an interface called Actor which represents the entity which performed some action in the product, which is often a User but could be a handful of other types. We also have some type names that are longer and much more specific like EventsCalendarDateTime which belong to specific sub-products and have product-centric nuance that would be inappropriate for more generic shared types. In general this balance has worked for us: terse names for broadly used types and specific unambiguous names for specific or single-purpose types.

@Cyberlane
Copy link

@leebyron my only concern with your suggestions is that the Docs link within the GraphiQL will show a massive list of mutations under Mutation. Is there perhaps a way to decorate each item with some type of Category which will only affect the generated docs, whilst leaving the actual schema alone?

Our schema has two entry points, which is really nice.

Our mutations however are in the hundreds... and without being able to split them up a bit, the generated documentation becomes useless to our developer teams.

@syrusakbary
Copy link

@Cyberlane this issue might be related #252 :)

@jhclouse
Copy link

The ideal situation is one in which you have complete control over the design of your schema and can justify a well-crafted set of type names. Unfortunately, many of us are in a different situation: we have an ever-growing and ever-changing set of disparate backend data sources described with something like Swagger and would love to be able to import them on the fly without curating them. Maybe namespaces aren't the best idea. But it would be great to have some kind of support for this scenario.

@isaksky
Copy link

isaksky commented Jun 30, 2017

@leebyron For cases where you know the object you would like to mutate, but don't know what cutesy name your colleagues decided to give the mutation (updateStory, changeStory, likeStory), I think this would get annoying. Think about this: why do we organize our functions into modules and namespaces as programmers? Don't those reasons also apply here?

Also, what about allowing it only for top level fields? A lot of what I see in this thread looks messy/overkill, but allowing it just for the top level would solve most of the problem. Fields after the first level already have a context, so further namespacing after that may cause more problems than it solves.

@KieronWiltshire
Copy link

https://github.com/Quture/app/issues/1

This is exactly what I need for ^^

@RickMoynihan
Copy link

Hi,

I'm pretty new to GraphQL, so please take my comments with a pinch of salt, but I see the need for namespaces for some usecases, and I think there are several distinct reasons to want them.

  1. If you're generating your schemas dynamically for example from a database schema then the possibility of collisions is undesirable, and having to prefix fieldnames/typenames/enums etc is pretty ugly.
  2. More importantly without namespaces it's hard to see how it's possible to share schemas and target them to create portable clients across different services. Without them how do I know that the field droids contains the rebel droids I'm looking for? Namespaces would help turn schemas into contracts and enable extensibility and discovery.

You might say why do we need portable clients? But we already have the need for one as the graphiql IDE is used across many implementations and it appears to rely on __schema being a contract with the server. The use of the __ prefix here seems to be a tacit acknowledgement of the role of namespaces as __schema really means graphql/schema (to borrow the syntax of this issue). The problem is that __schema is effectively now reserved, embracing namespaces would be embracing 3rd party extensibility and would turn a closed system into an open one.

Namespace & module systems often allow importing a namespace as an alias, e.g. you could imagine something like the following (inspired by SPARQL), though I suspect you could find a prettier syntax:

ALIAS myns: <http://foo.com/mynamespace> 
ALIAS schema: <http://schema.org/>

{
  schema/name 
  myns/name
}

Unnamespaced names with the exception of __schema could then default to being in an anonymous namespace for backwards compatibility.

@leebyron's idea of putting this data into the introspection system sounds like an interesting proposal, though I'm not yet sure if it would be equivalent to first class namespace support.

@thecaddy
Copy link

This should happen. Lee may not support it but the standard is bigger than FB now.

👍

@alloy
Copy link

alloy commented Nov 23, 2017

I don’t want to really double post and definitely don’t think my thoughts on the topic are crystallised well enough to actually partake in this debate, so for now I wanted to just link to some rough thoughts on this subject in the context of ‘stitching’ schemas from various services ardatan/graphql-tools#495 (comment)

@b-jsshapiro
Copy link

The field import idea that I introduced above does not work. Please ignore.

@Sytten
Copy link

Sytten commented Feb 22, 2021

I think we should start a working group to champion the namespaces. It is a big change that won't be done unless there is some organization to write the formal proposal.

@b-jsshapiro
Copy link

I think we should start a working group to champion the namespaces. It is a big change that won't be done unless there is some organization to write the formal proposal.

Funny you should say this. @zcourts and I decided several weeks ago to come up with a draft proposal. I'm waiting for his feedback, and I realized that I maybe should rearrange things to make them more clear. Right now it's a Google Doc, but I hope we can turn it into an organized proposal shortly.

@rivantsov
Copy link
Contributor

rivantsov commented Feb 27, 2021

Hi everybody
I am really interested in the WG and coming RFC and would like to participate/contribute, if only read the early drafts and propose comments, strongly-opinionated as you might expect :)
I have a coming project, POC for now, GraphQL API over big bank system; number of expected types is huge, 5K tables in database plus hundreds of external/internal services with their own models. I don't need to experience it first hand to know that there will be huge problems with that number of types in a single namespace, and there will be huge number of mutations. I know it's not feasible to get it into final spec in this timeframe, but I would be ok with early RFC draft to go with it, even without support from GraphiQL or other clients.

And it's not just me of course. I think this issue is LOOONG overdue, I am surprised to see it lingered for so long; it is clear from this and other posts that this is a huge pain. And simply from experience of working with BIG systems.
I don't buy this argument "We have 10K types at FB and we are OK", we have leaked opinions about ridiculous names out there (see Robert Zhu talk A case against GraphQL https://www.youtube.com/watch?v=djKPtyXhaNE), and comments about other systems - no, these ridiculous names are not OK. We are not OK. It is urgent, past due issue for other folks who already implemented large systems and experienced all the pain and tried various workarounds with quite limited 'success'.

Just wanna induce a sense of urgency. If we want GraphQL to live and prosper, we need to make it friendly for big systems.
I have my own GraphQL server+client implementation in .NET here: https://github.com/rivantsov/ngraphql, that's what I plan to use; I am open for experimentation with SDL changes, playing with syntax is no problem, it is quite easy, just tweak the grammar, so it can be a good playground.
Just suggesting my help cause it is really urgent and important stuff
thank you
Roman

@jxnu-liguobin
Copy link

I think the / syntax is great ,with the current GraphQL spec,we need mount the on GraphQL ObjectType to another bigger GraphQL object as a field and a new name,like Mount Dummy type to a bigger graph as dummyService field.

pinshen zhe li du you ni .

@LunaticMuch
Copy link

Just wanna induce a sense of urgency. If we want GraphQL to live and prosper, we need to make it friendly for big systems.

I do agree. In my daily work, the lack of namespaces is a challenge. If you create an enterprise endpoint for a big company, or for a company which operates in many sectors, despite all your careful approach with naming, the clash of type is always there waiting for you.
I am not advocating namespaces are needed so everybody can relax and use generic words, rather, because with Agile most of work is done case by case, onboarding and developing pieces of the schema by iterations, it's not always easy to see an object name can eventually clash with another tomorrow.
Nonetheless, if you want to scale parallel schema development across different use cases, you can't end with a strict governance on schema naming which will turn into a single point of conflict as nobody can own its namespace.

@justlevine
Copy link

Another use-case can be seen in the emerging WPGraphQL ecosystem. similar to the microservices or enterprise use-cases, except users arent writing their own schema, but rather using essentially premade microservices written decentralized by a myriad of developers with an expectation that everything will work together.

And unlike FB's approach, you cant realistically run integration tests against a decentralized ecosystem.

(Yeah yeah, WordPress is for luddites, but considering it powers more than 1/3 of the internet, thats a lot of websites that would be better served with GraphQL).

@rlhagen
Copy link

rlhagen commented Jan 20, 2022

There are certain places where namespaces make sense and alternative solutions will not work or become so cumbersome that using GraphQL becomes painful. Our system allows users to create GraphQL schemas at runtime and it's also based on a plugin model. So as a backend framework developer, I have no idea what the types will look like on any given system. We had to introduce our own version of namespacing in order to prevent this problem. I can't rely on compilation, tests, etc to make sure there are no naming collisions.

@andreiborisov
Copy link

I'm currently designing a highly complex yet decoupled system and the lack of namespaces is a big hurdle we're currently facing, while naming conventions help to a certain degree, enforcing them is unpractical due to how hard it is when you have multiple unrelated parties involved

@eric-jahn
Copy link

eric-jahn commented Feb 14, 2022 via email

@acao
Copy link
Member

acao commented Feb 14, 2022

This is a fascinating proposal! I’ve been following it for a while. Glad to see more cases being made. The impact across many graphql ecosystems would be immense - but imagine what other features this could unlock? I have also seen this in large schemas, where type names become increasingly complex, people use underscores to delimit faux namespaces, etc

@eric-jahn You can open a branch for graphql-js to get started, which is used by apollo, relay and urql clients, and is also used by many node.js graphql schema server implementations as well, such as apollo server, helix, etc. Some which don’t need AST like mercurius use graphql-jit.

What I found super helpful when working on the input union PRs was using TDD. graphql-js has phenomenal test coverage, much of it using literal graphql operations.

Also noting that this proposal needs someone to enlist themselves as a champion still.

@b-jsshapiro
Copy link

b-jsshapiro commented Feb 14, 2022 via email

@rivantsov
Copy link
Contributor

@b-jsshapiro - I am very interested in what you said; can you please contact me directly at rivantsov-at-gmail.com, or thru post/issue here: https://github.com/rivantsov/ngraphql . I am in a quest to challenge the belief that c# and other strongly typed languages are not so fit for GraphQL (and especially clients), and I would like to hear more if you don't mind. thanks in advance
Roman
PS I live not far, Sammamish! just a note

@b-jsshapiro
Copy link

b-jsshapiro commented Feb 15, 2022 via email

@rivantsov
Copy link
Contributor

b-jsshapiro, I opened a new thread for continuing, I have a few more questions, but this subject is out of place here;
new thread: rivantsov/ngraphql#25
I will post there shortly. but before we move there, pls clarify PIM system - is it "Product Information Management" system? you'd better spell out acronyms on first use. thanks

@LunaticMuch
Copy link

This is a fascinating proposal! I’ve been following it for a while. Glad to see more cases being made. The impact across many graphql ecosystems would be immense - but imagine what other features this could unlock? I have also seen this in large schemas, where type names become increasingly complex, people use underscores to delimit faux namespaces, etc

@eric-jahn You can open a branch for graphql-js to get started

Can you both publish here the branch as well? I do not see it (yet).

Also noting that this proposal needs someone to enlist themselves as a champion still.

Not good at coding, but I can help championing this. I am sure there would be a value also for system dealing with federation like Apollo. Federation does not address the problem of a single namespace. I've seen and dealt already with types long 60+ chars; yes they are super clear, but also ugly to read.

@eric-jahn
Copy link

@LunaticMuch @acao What should we call the branch? Maybe "graphql-namespaces"? I don't know how much time I have to devote to this, but I can definitely help out. I see GraphQL as the new Sparql for Knowledge Graphs/RDF.

@LunaticMuch
Copy link

@LunaticMuch @acao What should we call the branch? Maybe "graphql-namespaces"?

Looking at other names maybe schema-namespaces can be a good name.

don't know how much time I have to devote to this, but I can definitely help out. I see GraphQL as the new Sparql for Knowledge Graphs/RDF.

It is a nice way to see it. You share meaningful data with GraphQL and this translates into information and knowledge (well I know, it's a kinda philosophical statement).

BTW @acao should not this be first (or also) an update to GraphQL specifications? Are we going to think how to make it happen in graphql-js library before proposing an update to specs?

@Peeja
Copy link

Peeja commented Feb 23, 2022

I see GraphQL as the new Sparql for Knowledge Graphs/RDF.

Oh, there's some prior work here! Have a look at GraphQL-LD. It applies JSON-LD's concept of contexts—which tie globally unique IRIs to friendlier key names within the scope of a particular JSON document, thus implementing a kind of namespacing—to GraphQL queries. So it's literally built to query over RDF-style graphs.

@Sytten
Copy link

Sytten commented Jun 5, 2022

@benjie Will the issue of namespacing be covered under the new composite schema WG? I do feel strongly that it should be part of the discussion as this is a common pain point of the current integrations of schemas.

@benjie
Copy link
Member

benjie commented Jun 5, 2022

Should it be determined at the composite schemas WG that namespacing is the desired solution to this problem, then namespacing would need to make its way through the regular spec process as part of the spec WG to enable the composite schemas spec to use it. I definitely imagine that the composite schemas WG will result in some changes in the GraphQL spec proper, though I suspect it'll be changes along the lines of schema metadata (e.g. #300) rather than namespacing. Who knows though? Only time will tell!

@eric-jahn
Copy link

I think we need to create a formal standalone recommendation for namespacing within the GraphQL Spec WG (referencing OWL ontologies, vocabularies, and even JSON and XML Schema namespaces). That way, we aren't trying to rapidly shoehorn it into other GraphQL specification efforts, and it can be fully vetted on its own. I'm willing to help with that effort, and to rope in others to support it. Does anyone here have the means to establish a recommendation workgroup within the GraphQL community? Admittedly, I'm not very familiar with how the GraphQL spec is governed. It looks like the GraphQL Foundation, hosted by the Linux Foundation governs it, but I need to learn more about how it works.

@benjie
Copy link
Member

benjie commented Jun 5, 2022

Please have a read of the CONTRIBUTING guide, changes to the spec take place through RFCs. Currently this topic is at RFC0, the next step would be to try and advance it to RFC1. I advise that you find a champion (perhaps yourself) and have them work on an RFC document; RFC documents are typically filed here: https://github.com/graphql/graphql-wg/tree/main/rfcs . If you have a solution in mind then you can start making the spec edits in a PR against this repo, and then present it to the GraphQL Working Group for feedback. Please feel free to reach out to me (@Benjie) on the GraphQL Discord ( https://discord.graphql.org ) in the #wg channel and I'll be happy to provide any more guidance you need.

@eric-jahn
Copy link

To discuss this more informally, we have created a discord channel for graphql namespaces: https://discord.com/channels/625400653321076807/1001141142399750185

@jzabroski
Copy link

Interesting thread. I'm fairly new to GraphQL. Wrote a GitHub GraphQL query a few months ago to tabulate event data. In my own opinion, the Apollo Server docs nail this issue down with Tech Note 2: Namespacing by Separation of Concerns, where they note you can effectively create artificial namespaces:

To improve the logical organization of our graph's capabilities, we can define namespaces for our root-level operation fields. These are object types that in turn define query and mutation fields that are all related to a particular concern.

{skip a bunch of example code}

They then go on to say there is a key drawback:

Unlike all other fields in a GraphQL operation, the root-level fields of the Mutation type must be resolved serially instead of in parallel. This can help prevent two mutation fields from interacting with the same data simultaneously, which might cause a race condition.

{skip example code}

With namespaces, your mutation fields that actually modify data are no longer root-level fields (instead, your namespace objects are). Because of this, the mutation fields are resolved in parallel. In many systems, this doesn't present an issue (for example, you probably want to use another mechanism in your mutation resolvers to ensure transactional consistency, such as a saga orchestrator).

@eric-jahn
Copy link

A lot more discussion recently in the Discord channel mentioned above, as well. Hmm ... resolving namespaces by Separation of Concerns sounds problematic to me, since the common use case for namespaces are to commingle data elements across namespaces in a single API request/response, XML complex element, RDF triple, etc.. The separation then has to exist at the namespace definition level (schema, ontology, etc.).

@cyraid
Copy link

cyraid commented Apr 1, 2024

Any movement? I'm just starting to use a large library API written with graphql and noticed that there are a very large amount of queries in root, and it seems like a complete mess.

REST works nicely in the fact that you can make it modularized. Wanna find /users/* related methods in most frameworks? It's usually organized and you can find the controllers ready and each method builds off of the class defined route.

Namespaces would essentially do similar as others find out quickly, but 8 years later makes me feel like it might not go forward.

Perhaps a different approach could radically change graphql. Implementing different routes.

Having a query like /users/all() followed by a second query /admin/settings/get(something) would be pretty nice. REST-ish but also graphQL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👻 Needs Champion RFC Needs a champion to progress (See CONTRIBUTING.md) 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md)
Projects
None yet
Development

No branches or pull requests