Developers

Create, Update, and Delete Salesforce Data from LWC Without Apex

By Gaurav Singh

Updated March 05, 2026

Most of the Salesforce Developers, I’d assume, are already aware of GraphQL API. While most developers are familiar with querying data using GraphQL in Lightning Web Components (LWC), the addition of mutations takes this a step further – modifying Salesforce data via the GraphQL API without having to write Apex. 

Let us explore what GraphQL mutations are, how to use them in LWC, and provide practical examples of sObject record(s) manipulation.

What Are GraphQL Mutations?

In GraphQL, mutations are operations that provide an entry point for create, update, and delete operations on Salesforce objects. Hence, we now have two operation types in Salesforce’s GraphQL API – namely, Query and (newly GA) Mutation. The mutation operation only supports UI API supported sObjects, as it uses the UI API under the hood for the operations. 

Curious enough? Let us see how it looks and works with Lightning Web Components.

Using Mutations in Lightning Web Components

In an LWC, mutations are executed imperatively. Salesforce provides the executeMutation function from the lightning/graphql module for this purpose.

Importing and Setup

import { LightningElement } from 'lwc';
import { gql, executeMutation } from 'lightning/graphql';

Formulating Mutation Query

const query = gql`
  mutation <OperationName> {
    uiapi {
      <objectApiNameAndOperation>(input: {
        Id: "...", // Id is only required for update and delete operations
        <ObjectApiName> : { // ObjectApiName property is only required for create and update operations
          <FieldApiName>: value,
          ...
        }
      }) {
        record { // Used to specify the fields to fetch; only valid for create and update operations
          Id
          Field1
          Field2
        }
        Id // For delete operations only
      }
    }
  }
`;

The key syntax to understand is the use of the gql object. gql is a JavaScript template literal function that parses the query. A template literal allows you to create a string with embedded expressions, string interpolations, multiline strings, and HTML templates.

Invoking executeMutation Method

const result = await executeMutation({ query: mutation });

Note: You cannot use @wire with mutations, everything must be handled imperatively. 

Now that we are acquainted with the syntax, let us see how we can use GraphQL mutations to create, update, or delete record(s) of a custom object.

Example Response for Creating an Account Record

{
    "data": {
        "uiapi": {
            "accountCreate": {
                "Record": {
                    "Id": "001Ws00005CU3biIAD"
                }
            }
        }
    }
}

Usage Examples

Create a New Record

async handleCreate() {
    const mutation = gql`
        mutation CreateExpenses {
            uiapi {
                Expense__cCreate(input: {
                    Expense__c: {
                        Description__c: "${this.description}"
                    }
                }) {
                    Record {
                        Id
                        Description__c {
                            value
                        }
                        Name {
                            value
                        }
                    }
                }
            }
        }
    `;
    const result = await executeMutation({ query: mutation });
    console.log('Mutation result:', result);
}

Update a Single Record

async handleUpdate() {
    const mutation = gql`
        mutation UpdateExpense {
            uiapi {
                Expense__cUpdate(input: {
                    Id: "${this.expenseId}",
                    Expense__c: {
                        Description__c: "${this.description}"
                    }
                }) {
                    Record {
                        Id
                        Description__c {
                            value
                        }
                        Name {
                            value
                        }
                    }
                }
            }
        }
    `;
    const result = await executeMutation({ query: mutation });
    console.log('Mutation result:', result);
}

Apart from the actual mutation syntax, a key piece of mutations is defining how the response from the API will be formed. The Record object defines a follow-up GraphQL query that will produce that result. In doing so, you not only define how the data will change but also the precise feedback that is returned once complete. 

Response

{
    "data": {
        "uiapi": {
            "Expense__cUpdate": {
                "Record": {
                    "Id": "a00Ws00000qGlGMIA0",
                    "Description__c": {
                        "value": "Updated DESC"
                    },
                    "Name": {
                        "value": "Exp-0000006"
                    }
                }
            }
        }
    }
}

Multiple Operations in a Single Request

Yes, it is indeed possible to perform multiple record operations in a single request (despite not currently being documented in the LWC guide and only in the GraphQL API doc). 

In the following example, we will be performing 3 operations in a single request:

  • Operation 1: Alias firstAcc; creating an Account 1 without a name.
  • Operation 2: Alias secondAcc; Creating a second Account with Name as Account 2.
  • Operation 3: Alias updateSecondAcc; updating the Account’s name – which was created in the second operation – by referencing its record Id. The syntax for referencing the record Id is <FieldName> : @{OperationAlias}.

Please note here the use of allOrNone input. By default, it is set to true. By setting allOrNone to true, you can force a rollback when any of the operations fail in the request. If set to false, only the failed operation is rolled back and not the successfully executed ones.

async handleMultipleOperations() {
    const mutation = gql`
        mutation MultipleExpenseOperations {
            uiapi (input: {allOrNone: false}) {
                firstAcc: AccountCreate(input: {
                    Account: {
                        Rating: "Hot"
                    }
                }) {
                    Record {
                        Id
                    }
                }
                secondAcc: AccountCreate(input: {
                    Account: {
                        Name: "Account 2"
                    }
                }) {
                    Record {
                        Id
                    }
                }
                updateSecondAcc: AccountUpdate(input: {
                    Id: "@{secondAcc}",
                    Account: {
                        Name: "Second Account"
                    }
                }) {
                    Record {
                        Id,
                        Name { value }
                    }
                }
            }
        }
    `;
    const result = await executeMutation({ query: mutation });
    console.log('Mutation result:', result);
}

In the above example, the expected result is: 

  • Operation 1: Fails with the “Required field (Name) missing” error.
  • Operation 2: Successfully creates an Account with the given name.
  • Operation 3: Successfully updates the name of the Account created in Operation 2.

Note: Using aliases for operations is a good practice as it allows you to avoid conflicts and provides better readability.

Current Limitations of GraphQL Mutations

While GraphQL mutations are powerful, there are a couple of constraints to be aware of. 

  • Child relationship creation isn’t supported in a single mutation operation. You can create a record but not its child records (as nested payload) in the same operation. However, you can create a parent and child in a single mutation as different options.
  • If you are executing dependent operations in a single request, then all the dependent operations will either all execute successfully or fail collectively.

Summary

The introduction of GraphQL addresses the pain points of app developers building across various platforms, as it adheres to the industry specifications used globally by everyone. 

GraphQL mutations empower developers by introducing a flexible, schema-driven way to modify Salesforce data right from Lightning Web Components or via the API. 

The Author

Gaurav Singh

Gaurav Singh is an experienced developer and architect who has worked with Salesforce since 2017. He holds 13 certifications across the disciplines of development, administration, and architecture. He chooses to write under this pseudonym for SF Ben.

Leave a Reply

Comments:

    Richard Brescia
    February 18, 2026 6:19 pm
    This would mean that the activity to update/create the record would be initiating from the Client rather then the SF Server. How impactful could slow or inadequate connects be to this functionality? Trying to understand the Pro's or Con's are to utilizing this?