GraphQL Mutations in LWC — Create, Update, and Delete Without Apex


No more Apex wrappers for basic DML. executeMutation brings full record write operations directly to your LWC JavaScript.

⚡ SalesforceBolt — Source Code
batra-kapil / salesforcebolt-lwc — graphql-mutations
Full working examples: create, update, and delete with executeMutation

The GraphQL wire adapter in LWC has been great for reading data reactively. But write operations — creating, updating, deleting records — still needed Apex. That changes now. executeMutation from lightning/graphql brings full DML capability directly to LWC JavaScript, no Apex required.

What's New

According to the official Salesforce Developer Blog, GraphQL mutations are now available in LWC. Salesforce introduced the newest version of the GraphQL wire adapter (lightning/graphql) in Winter '26. This release adds support for using GraphQL beyond just querying — adding the ability to create, update, and delete records via the GraphQL Mutations API.

This fully unlocks bulk updates and tree saves for LWC without custom Apex, bringing richer data-driven applications to life.

The Core Function: executeMutation

According to the official executeMutation API reference, you import executeMutation from lightning/graphql and call it imperatively. It accepts an object with three properties:

PropertyRequiredDescription
queryYesParsed GraphQL mutation query. Must be parsed using the gql template literal function.
variablesNoAn object providing GraphQL variables. Must include an input argument with the record Id and fields.
operationNameNoSelects which operation to run if the query defines more than one. Recommended for server-side debugging.
💡 executeMutation is imperative only — no @wireUnlike the GraphQL wire adapter, executeMutation is not supported with the @wire annotation. You call it imperatively from a JavaScript function — typically on button click or form submit. The return value includes data and errors (plural — not error).

Create a Record

When creating a record, include all required fields, include only createable fields, and assign IDs to Reference fields using their API name. According to the official docs, use the refresh method after creation to ensure new records appear in existing query results.

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

const CREATE_CONTACT = gql`
    mutation CreateContact($input: CreateContactInput!) {
        uiapi {
            ContactCreate(input: $input) {
                Record {
                    Id
                    FirstName { value }
                    LastName  { value }
                }
            }
        }
    }
`;

export default class GraphqlCreate extends LightningElement {
    firstName = '';
    lastName  = '';

    async handleCreate() {
        const { data, errors } = await executeMutation({
            query: CREATE_CONTACT,
            variables: {
                input: {
                    ContactCreate: {
                        FirstName: this.firstName,
                        LastName:  this.lastName
                    }
                }
            },
            operationName: 'CreateContact'
        });

        if (errors?.length) {
            console.error('Mutation errors:', errors);
            return;
        }

        console.log('Created:', data.uiapi.ContactCreate.Record.Id);
    }
}

Update a Record

When updating, include the ID of the record, include only updateable fields, and assign Reference field IDs using their API name. The output field is Record. According to the official docs, use refresh to ensure updated records are reflected in existing query results — though the official blog notes that updated field values may propagate to subscribed LDS wire adapters automatically when cached data overlaps.

graphqlUpdate.js
import { LightningElement, api } from 'lwc';
import { executeMutation, gql } from 'lightning/graphql';

const UPDATE_CONTACT = gql`
    mutation UpdateContact($input: UpdateContactInput!) {
        uiapi {
            ContactUpdate(input: $input) {
                Record {
                    Id
                    Phone { value }
                }
            }
        }
    }
`;

export default class GraphqlUpdate extends LightningElement {
    @api recordId;
    phone = '';

    async handleUpdate() {
        const { data, errors } = await executeMutation({
            query: UPDATE_CONTACT,
            variables: {
                input: {
                    ContactUpdate: {
                        Id:    this.recordId,
                        Phone: this.phone
                    }
                }
            },
            operationName: 'UpdateContact'
        });

        if (errors?.length) {
            console.error('Update errors:', errors);
            return;
        }

        console.log('Updated phone:', data.uiapi.ContactUpdate.Record.Phone.value);
    }
}

Delete a Record

When deleting, include only the ID of the record. According to the official docs, deleted records are properly removed from LDS wire results automatically — no manual refresh required.

graphqlDelete.js
import { LightningElement, api } from 'lwc';
import { executeMutation, gql } from 'lightning/graphql';

const DELETE_CONTACT = gql`
    mutation DeleteContact($input: DeleteContactInput!) {
        uiapi {
            ContactDelete(input: $input) {
                Record {
                    Id
                }
            }
        }
    }
`;

export default class GraphqlDelete extends LightningElement {
    @api recordId;

    async handleDelete() {
        const { data, errors } = await executeMutation({
            query: DELETE_CONTACT,
            variables: {
                input: {
                    ContactDelete: {
                        Id: this.recordId
                    }
                }
            },
            operationName: 'DeleteContact'
        });

        if (errors?.length) {
            console.error('Delete errors:', errors);
            return;
        }

        console.log('Deleted record:', this.recordId);
    }
}

Data Consistency: When to Refresh

According to the official Salesforce Developer Blog, Lightning Data Service keeps record data consistent across UIAPI and GraphQL — but there are some important nuances:

OperationRefresh needed?Notes
CreateYesNew records won't appear in existing query results until refreshed
UpdateSometimesUpdated fields may propagate automatically when cached data overlaps. Not always required.
DeleteNoDeleted records are properly removed from LDS wire results automatically

GraphQL Mutations vs. Apex DML — When to Use Each

ScenarioUse GraphQL MutationsUse Apex
Create / update / delete UI API-supported sObjects✅ YesWorks too, more boilerplate
Bulk operations on multiple records✅ Multiple mutations in one call✅ Also works
Complex business logic before/after DML❌ Not ideal✅ Right choice
Non-UI-API supported objects❌ Not supported✅ Required
Mobile Offline use cases❌ Not supported✅ Required
Child relationship creation in one operation❌ Not supported✅ Required

Key Takeaways

🚀 GraphQL Mutations in LWC — Quick Reference
  • Import executeMutation and gql from lightning/graphql
  • Always imperative — @wire is not supported for mutations
  • Returns { data, errors } — check errors (plural, array) not error
  • Create: include all required fields + call refresh to update query results
  • Update: include record Id + updateable fields only + refresh if needed
  • Delete: include Id only — LDS removes it from wire results automatically
  • Child relationship nesting in a single mutation is not supported
  • UI API-supported sObjects only — use Apex for everything else
  • Use operationName for cleaner server-side debugging

GraphQL mutations complete the picture for data management in LWC. You can now read and write Salesforce data entirely through GraphQL without a single line of Apex for straightforward CRUD operations. That's a meaningful shift in how you architect LWC components for data-heavy UIs.

📄 Sources: GraphQL Mutations Now Available in LWC — Salesforce Developer Blog  |  executeMutation — LWC API Reference  |  SalesforceBolt GitHub — graphql-mutations

Watch on YouTube - Full Build And Demo

 If you have any question please leave a comment below.

If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !

Post a Comment

0 Comments