Single vs. Multiple Mutations for Serial Workflow

My team has an end-user requirement to “activate a feature” and then “save a profile” through a single user action (form submission).

As we begin the schema design process, my initial thought was to create a single activateAndSaveProfile mutation within the feature set’s namespace. This would abstract the transactional (and serial) workflow into one GraphQL operation. However, I’m now considering whether it might be better to expose two separate mutations - activate and saveProfile -within the same namespace, allowing them to be called serially but independently (read more about namespaces for serial mutations).

Example: Single Mutation (nested in namespace)

mutation ActivateAndSaveAccount(...) {
  namespace {
    activateAndSaveProfile(...) {
      ...
    }
  }
}

Example: Multiple Serial Mutations (nested in namespace)

mutation ActivateAndSaveAccount(...) {
  namespace {
    activate(...) {
      ...
    }
    saveProfile(...) {
      ...
    }
  }
}

A few considerations:

  • The “saveProfile” operation doesn’t appear to depend on any data returned from “activate”. If it does, we can always call the same API that checks activation status before saving the profile within the save profile resolver.
  • There’s a future requirement to allow profile updates, which means a “saveProfile”-type mutation will need to be exposed anyway.
  • We’re still working out the input/output structure for this functionality. So the absence of that detail here isn’t for simplicity - it’s genuinely still an “unknown.”
  • The Graph I’m working on was originally built as a thin API wrapper during the POC/MVP period - mostly direct mappings of underlying APIs to queries and mutations. I’m now migrating toward a Demand-Oriented Schema Design. That’s why I initially leaned toward a single mutation (it simplifies the consumer experience by abstracting the workflow into one call) rather than requiring consumers to understand and orchestrate multiple nested mutations in a specific order.

Has anyone faced a similar scenario? Which approach did you choose - single mutation or multiple? How did it play out? Were you happy with the decision, or do you wish you’d gone a different route?

As a follow-up, our team decided to move forward with the composite mutation, calling it activateHomeProfile (as opposed to something with ‘and’ in it) and build the underlying resolver / service / datasource logic to be easily re-used when/if we expose individual mutations for each portion of the transaction (for example, later when we need to ‘update home profile’ or if we ever need a stand alone ‘activation’ step).