Search code examples
apigraphqlapi-designstate-machine

GraphQL: Modeling evolving types / state transitions


This is an issue we have ran into multiple times now... very much looking forward to others' opinions!


Scenario Description (for illustration purposes):

Somebody visits our website, perhaps they fill out some forms, whatever. To us, this person is a prospect/lead. They have not been fully onboarded as a customer; they are simply a potential future customer.

Certain actions can be performed on these Prospects, such as adding certain data to their profile. Let's call this add_foobar_data. Of course, if they become a real customer (somebody consuming our service), we still need to be able to add/remove said data from their account.


Scenario (tl;dr):

  • Prospects can become Customers
  • Mutation add_foobar_data conceptually applies to both Prospects and Customers
  • Prospects only have a subset of data of Customers (they are a true subset; currently Customers have a lot of non-nullable fields Prospects do not have)

Options:

  1. Create a union type, e.g. Customerable. add_foobar_data would return a Customerable (or backref to a Customerable) rather than a specific type.

  2. Create separate mutations for modifying Prospects and Customers (add_foobar_data_to_prospect, add_foobar_data_to_customer)

  3. Everybody is a Customer! Make all those non-nullable fields on Customer that are not in Prospect nullable and add a new flag called isProspect (or isDraft if we want to change how we think about the flow).

  4. Perhaps some other approach I did not think of...


Anybody have thoughts on what is the best approach to this situation and why?


Solution

  • Ended up using an Interface since Prospect is a direct subset of Customer, and not by coincidence.