Hi folks! ![]()
Let’s imagine an application for scheduling service appointments.
A Customer can use the mobile app to create an appointment, but the same appointment can also be scheduled by an Employee (or Receptionist) on behalf of a customer via the company’s internal system.
I’m exploring schema design options for the createAppointment mutation and would love to hear your thoughts.
Option 1: Single mutation for all roles
type Mutation {
createAppointment(data: CreateAppointmentInput!): CreateAppointmentResponse!
}
- This mutation is used by both customers and employees.
- If the user is a customer, their
customerIdis inferred from the token/context. - If the user is an employee, the input needs to include a
customerId.
The problem: A customer could pass a customerId manually, even though they shouldn’t. It opens the door to misuse if not strictly validated.
Option 2: Role-specific mutations
type Mutation {
createAppointmentByCustomer(
data: CreateAppointmentByCustomerInput!
): CreateAppointmentResponse! @auth(roles: [CUSTOMER])
createAppointmentByEmployee(
data: CreateAppointmentByEmployeeInput!
): CreateAppointmentResponse! @auth(roles: [EMPLOYEE, ADMIN])
# Optional default
createAppointment(
data: CreateAppointmentInput!
): CreateAppointmentResponse!
}
- Clear separation of use cases.
- Inputs can be tailored for each role.
- Easier to apply role-based logic or validation at the schema level.
- If we have multiple features, the root
QueryandMutationtypes can become overloaded with fields, making it harder to navigate or organize operations efficiently.
Option 3: Role-based namespacing
type Mutation {
employees: EmployeesMutation! @auth(roles: [EMPLOYEE, ADMIN])
customers: CustomersMutation! @auth(roles: [CUSTOMER])
}
type EmployeesMutation {
createAppointment(data: CreateAppointmentByEmployeeInput!): CreateAppointmentResponse!
}
- Encapsulates mutations by role.
- Makes it clear at the top level who is allowed to perform what.
- Scales well if each role has many operations.
This logic also applies to queries (e.g., listing appointments, orders, etc.). An employee would need to pass the customerId, but the customer shouldn’t.
How would you do?