Skip to content

[RFC] __id field for unique identifiers #232

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

Closed
wants to merge 3 commits into from

Conversation

stubailo
Copy link
Contributor

This brings together many of the considerations about a __id unique identifier field into one document. There is still a lot of work to do before this becomes a merge-able diff on the spec:

  • Agree on field semantics specified in this PR
  • Restructure the spec so that the description for __id can live next to __typename
  • Write the change to the spec

@@ -6,3 +6,4 @@ build
out
node_modules
npm-debug.log
.vscode
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add this to your global gitignore ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call!

@stubailo
Copy link
Contributor Author

@calebmer @leebyron any initial thoughts?

@leebyron
Copy link
Collaborator

This is looking good - thanks for coalescing the RFC.

In my mind the biggest question is how __id should be represented in introspection. It seems like it should be a meta-field like __typename in as many ways as possible, however every object type has a name, so it's clear that you can always request __typename, but not every object type is uniquely identifiable or cacheable. We need some way to allow some types to have ids and others to not.

I'm not sure that expressing ids as nullable is what we want, for example if I fetched a bunch of User types that I expected to all be cacheable, and I encountered one with { __id: null } then I might have relied on a flawed assumption. Having ids be non-nullable is very valuable property to be able to rely on, so ideally we can enforce non-nullable ids as often as possible, if not as the default.

@leebyron
Copy link
Collaborator

Another piece of feedback is just at a high level - why should we be including this in the spec with additional behavior rather than simply making an id: ID! field a best practice for cacheable types? The spec should be as small as possible and no smaller, so we should ensure we have a strong argument for moving this from best practice to spec.

Specifically I think the argument "client caches would like to rely on this" is a little faulty as we already have client caches that rely on different forms of pagination and connection models with those as best practices and no impact on the spec.

I know we've talked before about changes to the GraphQL execution engine itself before that needed some way to identify objects that perhaps we should allude to in this RFC. For example, one of the reasons that led me to think that __id might be necessary was trying to figure out how GraphQL could respond in an already normalized graph format rather than it's current tree format.

@aweiker
Copy link

aweiker commented Oct 31, 2016

I recall seeing that the __ prefix was reserved for introspection and based on the current precedence, introspection is really around the type system. So therefore it feels odd that the value of __id would change for different instances of the same type. Which means, would this not be instance specific and better off served by having common conventions and practices of a meaningful id field?

@leebyron
Copy link
Collaborator

leebyron commented Nov 1, 2016

Which means, would this not be instance specific and better off served by having common conventions and practices of a meaningful id field?

More generally, __ is reserved for use by the GraphQL system itself which so far has only used this preserved space for introspection.

Practically, using a non prefixed field is only reasonable when suggesting common practice, and not appropriate for use by the GraphQL spec itself, since perhaps clients already have a field called id, and the potential for the spec to collide with user definitions is high.

In a final decision where this should be a common practice, then id: ID! would be the recommendation. In a final decision where this is encoded in the spec, then a __id meta-field would be more appropriate.

@calebmer
Copy link

calebmer commented Nov 1, 2016

Another piece of feedback is just at a high level - why should we be including this in the spec with additional behavior rather than simply making an id: ID! field a best practice for cacheable types? The spec should be as small as possible and no smaller, so we should ensure we have a strong argument for moving this from best practice to spec.

Specifically I think the argument "client caches would like to rely on this" is a little faulty as we already have client caches that rely on different forms of pagination and connection models with those as best practices and no impact on the spec.

In my opinion the specification of __id is perhaps the most important addition to the spec for GraphQL’s future. Cacheability is a side benefit of what an __id field gives us, the __id field gives us identity. Vanilla GraphQL is incredibly powerful for the first data query but after that first query reconciling data from mutations, subscriptions, and other queries is an incredibly hard problem. Falcor got the identity story right with paths (at the cost of good pagination), and resource identity was a fundamental principle of REST for good reasons.

Being able to identify data is important, so then the next question is how we identify that data. Whichever approach we choose, it must be consistent. There are problems with id: ID! which has become best practice thanks to Relay 1, chiefly that the name id conflicts with SQL field names. So then we need an alternative, which exists in renaming the field to __id. However, using a name like __id is useless unless the tooling agrees. In my opinion, fragmentation is not worth keeping this out of the spec.


So in summary, this issue (in my opinion) is the most important issue to resolve for the long term success of GraphQL, and since there are problems with the community solution (Relay id name choice) to avoid fragmentation we should standardize data identity with a solution which is both agreeable by the community and will help to build much better developer tooling.

@calebmer
Copy link

calebmer commented Nov 1, 2016

Also, just a thought, if instead of having __ids be null if they don’t exist on the type then they are a base64 encoding of a path to the data from the last __id?

{
  __id # Encoded value of an empty path or array: `[]`.
  a {
    __id # User defined to be the value `unique-id`.
    b {
      __id # Encoded path `["unique-id", "b"]`.
      c(x: true) {
        __id # Encoded path `["unique-id", "b", "c"]`
        alias: d {
          __id # Encoded path `["unique-id", "b", "c", "alias"]`
        }
      }
    }
  }
}

I don’t particularly like this idea, but @leebyron mentioned requiring non-nullable ids by default 😉. Ultimately I don’t think missing an __id on a user would be a huge deal in practice, it just wouldn’t be normalized by the client.

@stubailo
Copy link
Contributor Author

stubailo commented Nov 1, 2016

@calebmer coincidentally this is very similar to how the Apollo Client cache deals with missing IDs.

In a final decision where this should be a common practice, then id: ID! would be the recommendation.

This is pretty inconvenient if GraphQL is meant as a thin API layer, since people often have underlying model objects that already have an id field. __id, even if it's not built into GraphQL, seems like a reasonable recommendation because it's something everyone can follow, even if they already have a pre-defined id field.

Another piece of feedback is just at a high level - why should we be including this in the spec with additional behavior rather than simply making an id: ID! field a best practice for cacheable types? The spec should be as small as possible and no smaller, so we should ensure we have a strong argument for moving this from best practice to spec.

There's one big argument for this being in the spec, which is similar to @calebmer's - this gives GraphQL tools, services, and libraries the ability to reliably cache data coming from any GraphQL server. I'd argue that is a much more fundamental requirement than pagination.

Given that, having the __id field be queryable on every single object, even if the server doesn't want to present an ID for that field, is important for tools that want to be able to cache data but not run introspection ahead of time. Specifically, for Apollo Client it's incredibly advantageous that we don't need to require schema knowledge to do many useful GraphQL things. Even if the ultimate best solution to some problems requires introspection, caching is so useful that it's good to include in the "getting started" experience.

In the current situation:

  1. id can't be turned on by default because some servers expose a field called id that isn't unique, and
  2. Requesting the id from the client requires either manually typing that field in the query or doing introspection, so it requires extra setup and work

This means that people getting started with GraphQL can't get the benefits of caching without a lot of effort, and makes GraphQL seem less powerful out of the box. If this proposal or similar could be included in the spec, then every single GraphQL tool could have caching built in by default.

@josephsavona
Copy link
Contributor

josephsavona commented Nov 7, 2016

It's important to separate aspects of __id that would be convenient from those that are necessary to achieve certain ends.

It's already possible to write a GraphQL client that correctly caches data coming from any server. This can be achieved with product-specific configuration (e.g. a mapping of type names to the identifying field(s) to use) or with convention (as in Relay's "Object Identification" spec). Given that, __id is primarily a convenience for cache identification.

As @leebyron pointed out, though, other proposals may require something like __id:

  • A @defer directive that caused the server to return the data for a query in several stages. Clients would need some way to interpret subsequent responses. This may or may not be feasible without a way to easily identify the root object.
  • Pre-normalized responses. There is a tradeoff between response size and response processing time. For clients that normalize a response, it may be preferable to receive an already normalized response. This would require the server to know how to identify records, either via __id or some other mechanism.
  • Delta payloads for live queries and/or subscriptions. Informing a client about how the results of a previously executed query has changed could take several forms: returning an updated complete query result, or returning a partial result. A "delta" payload could rely on __id.

On the one hand, I do see a lot of value in __id from a client caching perspective. However, it seems more relevant in the context of future proposals. Would it make sense to flush out these more advanced use-cases first? I'm concerned that nuances of how __id would work could make these features more challenging. As an example, should @defer be allowed anywhere or only on types that have an __id? If it's allowed anywhere, how should a client interpret a deferred response that doesn't have a cacheable root id? It's even possible that __id isn't required for some of these features.

@stubailo
Copy link
Contributor Author

stubailo commented Nov 7, 2016

That's not the main reason I'm interested in this proposal. I mostly just think it's unfortunate that such a core feature of pretty much all GraphQL servers and clients is unspecified and requires extra configuration, which makes it harder to build generic tools. But let's take a look:

defer

I think this can easily be implemented without caching IDs. The new results can simply have a JSON path, in the same format as the error path in #230, which will allow the client to put the new result in the right place. Of course, that requires maintaining the original query result until the rest of the query results arrive, but I think that's preferable to requiring caching IDs for any deferred fields.

Normalized responses

From my understanding of how Relay and Apollo work, a normalized transport wouldn't help either one. Both clients have different opinions about how the normalization should be done, and so neither would use the graphql spec normalization directly. Perhaps a normalized transport would make the response size more efficient, but in that case it might be able to use something like JSON paths? Although I agree it would be more compelling to have it use a standard ID, especially since it would only make sense to normalize repeated objects which would need to be identified.

Delta payloads for livequeries

I think these and @defer should ideally be the same, since @defer seems like just a special case of sending a result patch where the path doesn't intersect with already received data.


In my mind, this is a case of taking something that is very clearly a "best practice" in GraphQL, that almost any serious tool needs to take advantage of, and making it "standard".

I think almost anything can be done without a standardized __id, so my feeling is that it will never be more than a convenience. But a lot of things in GraphQL are a convenience so I feel like that shouldn't disqualify this proposal.

@OlegIlyenko
Copy link
Contributor

OlegIlyenko commented Nov 14, 2016

Just wanted to add my 5 cents into this discussion. In general, I don't have anything against a built-in concept of id in GraphQL spec. But I would strongly agree with @leebyron: not all objects in the schema have an ID. Some of them do, in this case the id field must be not-null.

I also thinking about implications on the end-users who are writing a GraphQL server and possible complexity of GraphQL server implementation itself. For instance, it would be very inconvenient if I need to explicitly define an ID for every single GraphQL object type in the schema (especially if they should be globally unique). I doubt that it would be even possible in most cases.

I also not very optimistic about generically inferring constructed IDs based on some real object IDs. For instance, give this schema:

type User {
  id: String
  profilePicture(size: Int!): Image
}

type Image {
  width: Int!
  height: Int!
  url: String!
  labels: [ImageLabel!]
}

type ImageLabel {
  name: String!
  description: String
}

and this query:

query AwesomePictures {
  user(id: "123") {
    id
    awesomePicture: profilePicture(size: 300) {
      awesomeLabels: labels {
        description
      }
    }
  }
}

According to the semantics of my data, only User has a semantic ID which is not globally unique (in my experience, many applications model data in this way), everything else may or may not have an ID which is unique within particular user (if you like DDD, then the Aggregate and Aggregate Root would be a good analogy).

What would be the ID of the labels in this case? Something like: "user:123:awesomePicture_size_300:awesomeLabels[0]", "user:123:awesomePicture_size_300:awesomeLabels[1]", etc.?

Maybe instead of defining an __id field in the spec, we can define an interface that has an id field, just like relay does:

interface __Identifiable {
  id: ID!
}

With this interface user can very precisely identify which objects do have an identifier and which don't. I think this will have a huge advantage not only for client-side caching, but also for normalized data transfer. I'm thinking about JSON Graph here. The problem is that we can't really unify particular object within different parts of the query because the same field name may have very different semantic value or even type (if alias is used).

But we have the similar situation with fragment unification. It is solved with OverlappingFieldsCanBeMerged validation rule, which ensures that fragments can be unified. If we have standard __Identifiable interface, then maybe we can write similar validation (thus introducing additional constraint) for identifiable types that must be "merge-able". Just a brainstorming idea (haven't put too much though into it yet).

@stubailo
Copy link
Contributor Author

stubailo commented Nov 15, 2016

It looks there's a consensus that having an __id field that is guaranteed to be queryable on every type, but is sometimes null, isn't something people want. I think it would allow great improvements for GraphQL clients that don't require special build tooling, but perhaps that isn't part of people's desires for how GraphQL should be used.

In my mind the biggest benefit would come from allowing __id to be queried on every selection set just like __typename, without knowing whether the underlying type actually has an ID or not.

Without that property, I think this is mostly indistinguishable from a client-specific convention to use a special interface like Node, which could be discovered through introspection as usual.

So there could be a different proposal that would:

  1. Add a special interface like Node to the specification, and
  2. Specify the semantics and name of the ID field, like __id and global uniqueness.

I also not very optimistic about generically inferring constructed IDs based on some real object IDs.

In my original proposal they would simply be returned as null when the server doesn't have a semantic ID to offer. I agree that generating non-semantic IDs on the server is not a good idea.

@OlegIlyenko
Copy link
Contributor

Now that I think about it, given this built-in Node interface, it should be straightforward to transparently define an __id: ID (nullable) meta-field in terms of it, which is available on all object types.

@calebmer
Copy link

The availability of __id on all types is a powerful property for simpler schemaless GraphQL clients, so I stand by it. However, I would rather see that split into another RFC and just define the global identity semantics of an __id field in this RFC if we could more easily get this RFC through.

At a minimum we should standardize the semantics of an __id field to avoid fragmentation as we have determined object identification is something all reasonably powerful GraphQL clients need.

@josephsavona
Copy link
Contributor

josephsavona commented Nov 17, 2016

Per @stubailo and @calebmer's comments above, I'd propose that we separate this into two proposals: defining the semantics of the __id field and a separate discussion about if/how GraphQL should make tradeoffs to allow "schema-less" clients.

__id Semantics

I would argue that the schema is one of the strengths of GraphQL, as it enables building client tooling. As such, the introspection results should accurately indicate the full list of fields that is selectable on any given type. This suggests that either __id should be selectable everywhere and nullable, or that it should be non-nullable and only selectable on types that implement it.

For clients it is very helpful to know statically which types (and therefore which fields in a query) are identifiable. We have used this knowledge to polyfill @defer and connection edge streaming in Relay, for example. If the introspection query were to indicate that all types had a nullable __id, then these types of polyfills would be much harder as the client would not have enough information to know how to split up a query.

Given this, I'd strongly prefer that we make __id non-nullable, required to have globally unique values, and only appear in the schema/introspection query where defined by the user for a given type.

Querying __id Everywhere & "Schema-less" Clients

This leaves open the question of whether it should be allowed to send a query that asks for __id everywhere,, even on fields whose type does not implement the field (the server could theoretically return null or omit the field for those types that don't implement it). I think it's useful to separate this discussion from this __id RFC: the two are only tangentially related.

Stepping back, this aspect of the proposal is really about whether the specification should allow clients to send _un_validated (and therefore possibly invalid) queries:

  • Selecting fields like id or __id that may not exist
  • Adding fragment spreads of an invalid type
  • Sending input objects with additional fields not defined in the schema

Our experience with Relay and our native GraphQL clients has shown the benefits of embracing the schema; any degree to which it may be inconvenient to load the schema in advance has been offset by all the possibilities that affords. That said, this is definitely something we should discuss more generally in a separate RFC.

Next Steps

@stubailo Thanks again for kicking off this RFC and discussion. What do you think about updating the text to reflect the above?

@stubailo
Copy link
Contributor Author

Does the shortened proposal basically come down to:

  1. If your schema defines globally unique IDs for some or all objects, they should be in a field named __id
  2. The __id field shouldn't be used for anything else
  3. __id is in the introspection result like any other field

Or is there anything else?

And yes, I think there could be a general discussion to be had about the benefits of schema-less GraphQL client libraries and tools, and some simple changes that could make them much more convenient to build and use. The benefit here is simplifying adoption of GraphQL as the next standard for APIs - such tools will inherently be easier to adopt than those which require special tooling or schema access, the same way that untyped languages are easier to get started with than typed ones, and generally require less tooling. Where would be the best place to have that discussion?

@josephsavona
Copy link
Contributor

Or is there anything else?

@stubailo That's a good summary, yup!

And yes, I think there could be a general discussion to be had about the benefits of schema-less GraphQL client libraries and tools [...] Where would be the best place to have that discussion?

How about opening another issue for this topic in order to start the discussion and get more input? It would be good to clearly define the goal first in order to ground the discussion, and then list out any technical challenges that make that goal harder to achieve under the current spec. I think we're one or two steps away from a RFC, as there may be better alternatives than just allowing __id to be selectable anywhere. Looking forward to discussing in more detail!

@leebyron
Copy link
Collaborator

Great conversation so far. Let me try to round up where we are and some decisions that need to be clarified and made:

id vs __id

First is what to name this field. The name id lends itself to user-created schema. Because __ is reserved by GraphQL introspection, we shouldn't be using it for user-created types and fields. However if this field is a "meta" field, then __id is more appropriate, making it more similar to __typename which is of course never defined in user-created schema.

Another notable drawback to id is that adding constraints to it would add a constraint for existing systems to work around should they want to expose some field called "id" which has different semantics. They would have to rename their other field.

I'll refer to it as __id through the rest of this comment, but the question still is open.

Should __id always have a value?

It seems clear from the conversation that if __id is queried on an object which is capable of providing ids, that it must provide a non-null value.

However should all types provide non-null __id? I think we've proven that's not really possible. Some combination of parent-id + field-path could be used, but there are issues with this approach.

Can the __id field be requested anywhere?

I think it's reasonable to consider an exception to the validation rules for meta fields. Meta fields are not part of a schema, so they have different rules.

Should there be an __Identifiable interface?

Not sure if this was proposed as a counter-proposal to __id having different validation rules.

How is __id represented in the schema language?

Are types which support the __id field required to declare it explicitly so as a regular field? If so, then perhaps id is more appropriate as that would make it not a meta field. Should the schema language having an @identifiable directive? It seems like most types would be identifiable, so perhaps non-identifiable should be called out differently?

How is __id represented in the introspection result?

If __id is a meta field, then it shouldn't appear as part of the schema (just as __typename does not), however some indication of a type being identifiable needs to be available if not all types are available, so schema-aware clients know what to expect.

@leebyron
Copy link
Collaborator

Here's a counter-proposal to consider: we could standardize a clarified version of the current best practice.

Constrain id with musts

Specifically:

Types are not required to provide a field id, however if they do it must:

  • be of type ID!.
  • return values unique for the entire schema domain.

A field named id is valid to be queried in any selection set. Execution behavior is unchanged, which means if id is queried on a type which does not implement it, then no entry is added to the response for that field.

Pros:

  • This is the simplest thing that works.
  • No changes are required to introspection.
  • No changes are required to the schema language.
  • There is no addition of new meta-fields.
  • Critically: this is backwards compatible with existing libraries & tools.
  • All Relay-esque apps and APIs continue to work.
  • Easy to auto-add to queries for schemaless clients.
  • Does not require interfaces.

Cons:

  • This highly constrains id as a field to use.
  • This change is potentially breaking with existing APIs if they use id in a non-best-practice way or of a different type.
  • Potentiall for confusion if non-refetchable, id sometimes used to refetch when used with a Node interface.

Alternative: Same, but __id.

Same as above, but replace id with __id. In my personal opinion the cons of this blurring the meaning of __ would be pretty damning for this particular approach.

Pros:

  • No collisions with existing APIs.

Cons:

  • This is not a meta-field, blurs the line as all other __ fields are meta.
  • Requiring people to define __id manually is confusing between user domain and graphql introspection domain.

@stubailo
Copy link
Contributor Author

Easy to auto-add to queries for schemaless clients.

I'm not sure this is a factor for id as compared to __id.

I think taking up the name id can be a pretty big disadvantage because then you have to start having fields like sqlId or something.

@leebyron
Copy link
Collaborator

Ya, to be clear the "Easy to auto-add to queries for schemaless clients." has nothing to do with id vs __id - that's just about the making the validation exception.

@leebyron
Copy link
Collaborator

leebyron commented Nov 23, 2016

I think taking up the name id can be a pretty big disadvantage because then you have to start having fields like sqlId or something.

Yeah - it certainly can require people to work around this which is a disadvantage for moving quickly, however perhaps it's an advantage for the design quality of the resulting APIs? Directly exposing SQL IDs is a "code smell" since it leaks implementation details about the API. (we had similar issues at Facebook - to interop with old APIs we exposed legacy_id on some types)

I could also argue that the "pit of success" would have us make the id field which corresponds to caching (and occasionally refetching) as easy to guess and use as possible. An API which exposes type-local SQL ids as id and global cacheable ids as __id could cause confusion. Which should a user of the API use? They will probably use the one called id since it's easier to type than __id.

Another thing to consider is the case where objects are both uniquely cacheable AND are refetchable. It is probably confusing to say that you should use the id field for refetching things, but use the __id field for caching things. Not only is that potentially confusing, but if an API exposes the same value for id and __id all of the time, then perhaps clients will only fetch one or the other but use the one value for both contexts. That might be fine up until the point where they stop returning the same value! Or for APIs where the two fields return different values, then it could be too easy to accidentally use the value for __id somewhere that expects id and vice-versa causing bugs.

I guess another way to rephrase this concern is that clear API design would lead us to use only id or __id but not both.

Should we actually allow for this kind of confusing scenario?

@calebmer
Copy link

calebmer commented Nov 23, 2016

I could also argue that the "pit of success" would have us make the id field which corresponds to caching (and occasionally refetching) as easy to guess and use as possible.

Deciding the GraphQL specification is going to favor one path or “put of success” over another, the specification begins to assume a certain use case which can be dangerous. Naming the field __id (to avoid collisions) is not just about preserving space for SQL id fields, but preserving space for new innovative GraphQL designs. The field name id for two ridiculous examples could stand for Indonesian (the language code of which is id), or Freud’s Id part of his psychic apparatus. More realistically by constraining the id field, applications like GatsbyJS, gdom, and PostGraphQL which generate a schema from the file-system, XML, and database respectively must design workarounds to avoid collisions.

All of these applications may be able to make use of identifying the data in their responses, but not all may appreciate the naming collision.


Alternative proposal:

After better understanding some of the hesitations around the __ prefix, and gaining some inspiration from @leebyron’s mention of an @identifiable directive here is a rough alternative direction we could go for the same benefits.

It seems as if the name of the unique cache-key field should really be a schema designer’s decision. We can (hopefully) agree that by specifying id we may limit creativity, and by specifying the name __id we introduce confusion and make the semantics of __ fields less clear. Since we can’t agree on a name, let us give the naming power to schema designers with a @identifier directive. It may look as follows:

type Person {
  _id: ID! @identifier
  name: String!
}

interface Node {
  id: ID! @identifier
}

type Post implements Node {
  id: ID! @identifier
  title: String!
}

Or:

type Person @identifiable(field: "_id") {
  _id: ID!
  name: String!
}

interface Node @identifiable(field: "id") {
  id: ID!
}

type Post implements Node @identifiable(interface: "Node") {
  id: ID!
  title: String!
}

A field on a type or interface may be marked as the type’s identifier field. That field must have a type of ID! and must take no arguments. A type must only have one field marked as an identifier. If a type inherits from an interface where one of the fields is marked as an identifier, the field on the type with the same name must also be marked as an identifier.

What the @identifier directive means semantically is that the value of the field is unique for all values of that type. Note that it does not mean the field is globally unique, just locally unique for that type. So an @identifier directive on the id field of the Relay Node interface would mean the same thing as it does now. The id must be unique across all other Node values.

In clients, the cache key would become the __typename combined with the identifier. So in the above example Person-${value1} or Node-${value2} would be the key.

In the introspection query if we wanted to get real meta, the __Type type’s name field could be marked as an identifier.

Pros:

  • No naming collisions. Gives schema designer total control over their types.
  • Backwards compatible with Relay 1 schemas. Just mark id as an identifier everywhere.
  • Users can have non-globally unique identifiers. They could use SQL serial ids or plain UUIDs and mark them with @identifier as long as they don’t inherit from an interface which marks the same field.

Cons:

  • No room for schemaless clients, may actually make the schemaless client use case much harder to implement. Unless we also wanted to add an __id or __identifierValue field which was always queryable and returned the identifier value. But then we are back to bikeshedding over __id.
  • More API configuration.
  • Requires a change to introspection queries.
  • Interaction between interface identifiers and type identifiers may be confusing.

@smolinari
Copy link

smolinari commented Nov 23, 2016

@stubailo - could you please explain this a bit more in detail?

And yes, I think there could be a general discussion to be had about the benefits of schema-less GraphQL client libraries and tools, and some simple changes that could make them much more convenient to build and use.

I don't mean to derail this conversation, but I'd really like to understand where you were heading with this, because if it is what I think it is, you get a 👍 from me. However, this is my confusion. If it is what I think you were getting at, then any definition of a fixed field type, even an ID, which is so common, basically kills my understanding, thus my asking for a bit of an explanation. 😄 I guess this is my question.

Isn't the notion of "variable schema" (I don't like the term schema-less, as it is inappropriate) and the necessity of an ID field contradictory? 😄

Scott

@stubailo
Copy link
Contributor Author

I'm going to close this PR since there doesn't seem to be a clear consensus about the design of such an addition to the spec, or whether it's necessary at all.

I am partial to Lee's idea in #232 (comment) about constraining any fields named id to be unique and of type ID!, however also mindful that this might break a significant number of non-Relay apps who have previously not been constrained to such a requirement.

I still deeply believe that standardizing the concept of an identifier for objects will make GraphQL more useful overall and reduce the amount of boilerplate and configuration most developers need to write, so if there is an agreement on how that can happen I'd be happy to write a PR for the spec.

@stubailo stubailo closed this Jan 16, 2017
@leebyron
Copy link
Collaborator

Thanks for your work so far on this. I'm still interested in a solution for broad identifiability. Hopefully we can find consensus on this in a future RFC

@ignaciojocano-ITH
Copy link

Was there any kind of follow-up on this closed proposal?

@glen-84 glen-84 mentioned this pull request May 15, 2022
@benjie benjie added the 🗑 Rejected (RFC X) RFC Stage X (See CONTRIBUTING.md) label Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🗑 Rejected (RFC X) RFC Stage X (See CONTRIBUTING.md)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants