Aquargin Way / Build Functions / Module 05

Create, Update & Bulkify

Now you'll write data — make new records, change existing ones, remove them — and learn the single most important performance rule on the platform: the bulkify rule. Get it right and your functions stay fast no matter how many records they touch.

5 units ~20 min Earn the Bulk Master stamp
Unit 1 of 5

Writing data: create, update, delete

So far you've read data with query and changed it in memory with assignment. To make those changes stick — to actually touch the database — you use one of three nodes.

  • create — adds brand-new records to an object.
  • update — saves changes to records that already exist.
  • delete — removes records.

There is no single, generic “write” node — you always pick the specific one that matches what you mean to do. Each of the three shares the same three settings:

  • object — the target object's API name (e.g. task__m, lead__m; yours may differ).
  • recordVariable — the variable holding the record (or records) to write. It must be a variable you've already declared and filled.
  • isList:true — flip this on when the variable holds a list and you're writing many records at once.
assignment
lead.status = "Won"
update
object: lead__m · recordVariable: lead

That's the whole shape of writing data: change a value, then commit it with the matching write node. The rest of this module is two ideas — how to use each node, and where not to put them (inside a loop).

There is no “DML” node

Some platforms lump all database writes into one “DML” step. Aquargin does not. You always choose create, update or delete explicitly. If you're looking for a node called DML, you won't find one — and that's by design.

For developers — why “DML” is split into three

“DML” (Data Manipulation Language) is the SQL umbrella term for INSERT, UPDATE and DELETE. On the board those map one-to-one onto the create, update and delete node types. Splitting them keeps each node's intent unambiguous: a create can't accidentally overwrite, an update can't accidentally insert. The recordVariable must be a declared variable — write nodes never invent data; they persist what your flow already built.

Unit 2 of 5

Creating records

To create a record you do two things in order: build it in an object variable with assignments, then place a create node that writes it.

The create node never makes data out of thin air — it persists whatever you've assembled in the variable you point it at. So the pattern is always “fill the variable, then create it.”

Single record vs. a list

The only difference between writing one record and many is the shape of the variable and one checkbox:

  • One record → an object variable. Leave isList off.
  • Many records → an object-list variable, and set isList:true so the node writes the whole list in one go.

Example: create a follow-up Task

Say a button should drop a follow-up task onto a lead. Declare an object variable task (of object task__m), fill its fields with assignments, then create it:

assignment
task.subject = "Follow up"
create
object: task__m · recordVariable: task
  1. Build the record in a variable

    Declare an object variable named task. With assignment nodes, set the fields you need — task.subject = "Follow up", task.dueDate, task.relatedTo = lead._id, and so on. (Field API names vary by org; you'll pick them from dropdowns.)

  2. Add a create node

    Place a create node after your assignments. Set object to Task (task__m) and recordVariable to task. Since it's a single record, leave isList off.

Creating many at once

Need a task for every lead in a list? Build each one and collect them into an object-list variable (with addToList), then point a single create node at that list with isList:true. One node, many records — which is exactly the mindset Unit 4 makes a rule.

Unit 3 of 5

Updating & deleting

Updating a record is a three-beat rhythm you already met in Module 02: load it, change it, save it. Deleting is simpler still — you just remove the record(s).

The Configure Update Record panel: select an object or list of objects to update records.
Fig 1 The real Update Record config — point it at the object (or list of objects) holding the record(s) to save. Create and delete take the same shape.

Updating: load → change → save

You can only update what you've loaded, so an update almost always follows a query:

query
load the Lead
assignment
lead.status = "Stale"
update
object: lead__m · recordVariable: lead
  1. Query to load the record(s)

    Run a query to pull the record into a variable — a single record into an object variable, or many into an object-list.

  2. Assignment to change the values

    Use assignment nodes to set the fields you want to change — lead.status = "Stale". Nothing is persisted yet; you're editing in memory.

  3. Update to save

    Add an update node. Set object to the target API and recordVariable to your variable. For a single record, leave isList off; for a list, set isList:true.

Deleting: remove the record(s)

A delete node takes the same object + recordVariable settings — point it at the record (or list) you want gone. As with the others, set isList:true when the variable is a list. You generally query first so you know which records you're removing.

Single vs. list — same node, one switch

Every write node — create, update, delete — behaves the same way: an object variable for one record, an object-list with isList:true for many. You don't learn three different nodes for “one” and “many”; you flip one checkbox.

For developers — update writes only what changed

An update persists the record held in recordVariable back to its object — the _id in that record tells the platform which row to write. That's why you load with a query first: the query brings back the _id (always include it in your field list) along with the current values. Change a field, update, and the record is saved with its id intact. A delete likewise keys off the _id of each record in the variable.

Unit 4 of 5

The bulkify rule

This is the most important performance rule on the whole platform, so read it twice: never put a query, create, update or delete node inside a loop.

Why it matters

Each of those four nodes is an expensive database operation — a round trip to the data store. That's fine once. But put one inside a loop over N records and you've just asked for N separate database operations. Two things go wrong:

  • It's slow. A thousand records becomes a thousand trips. What should take one operation now takes a thousand.
  • It hits governor limits. The platform caps how many database operations a single function may perform. Loop-inside writes blow through that cap and the function is stopped.

The fix is to do one operation on the whole list instead of one operation per record.

The pattern

It's three moves, and the order is everything:

  1. Query BEFORE the loop — pull all the records you'll need in one go.
  2. Inside the loop, only cheap nodes — condition, assignment, and addToList to collect records into a list. No database nodes here.
  3. Write AFTER the loop — a single create / update / delete on the collected list with isList:true.
query
load all records — BEFORE the loop
loop
for each record…
condition
↳ inside: does it qualify?
assignment
↳ inside: set the field
addToList
↳ inside: collect into toUpdate
update
isList:true on toUpdate — AFTER the loop

The loop's only job is to decide and collect. The expensive write happens exactly once, outside it, on the list you built.

The bulkify rule

Never place a query, create, update or delete node inside a loop. Query before the loop; collect with assignment / condition / addToList inside; do one bulk write with isList:true after. This applies to every function type — buttons, triggers, scheduled jobs and pages alike.

For developers — what “governor limits” actually cap

Functions run inside a per-execution budget tracked by the platform's governor: a maximum number of queries and DML operations per run. A query or write inside a loop multiplies the count by the iteration size, so even a modest list can exceed the cap mid-run and abort the function. Bulkifying keeps the count flat — one query, one write — regardless of how many records flow through. It's the same discipline as avoiding SOQL/DML in loops on other enterprise platforms: batch the I/O, iterate over data in memory.

Unit 5 of 5

A bulk update, end to end

Let's build the real thing: take a list of leads, mark every open one as Stale, and do it the bulkified way — one query, one update, no matter how many leads there are.

  1. Query the open leads — BEFORE any loop

    Start with a query on Lead (lead__m). Include the fields you'll touch — at least _id and status — and filter to the ones you care about (status Equal Open). Use take mode all and store the result in an object-list variable, say openLeads. One trip to the database, every record you need.

  2. Loop over them — collect, don't write

    Add a loop over openLeads. Inside the loop, use an assignment to set the current lead's status — currentLead.status = "Stale" — then addToList the current lead onto a second object-list variable called toUpdate. No query, create, update or delete lives in here — only cheap, in-memory work.

  3. Update once — AFTER the loop

    After the loop closes, add a single update node. Set object to Lead, recordVariable to toUpdate, and turn on isList:true. Every collected lead is saved in one operation.

query
Lead where status = Open → openLeads (BEFORE)
loop
for each lead in openLeads
assignment
↳ inside: currentLead.status = "Stale"
addToList
↳ inside: addToList → toUpdate
update
object: lead__m · toUpdate · isList:true (AFTER)

Whether openLeads holds five records or five thousand, this function makes exactly one query and one update. That's the bulkify rule paying off.

You're now a Bulk Master 🎉

Query before, collect inside, write once after — burn this pattern into muscle memory. It powers almost every serious automation on the platform. In Module 06 — Triggers, Jobs & Pages, you'll see this exact shape drive record-save triggers and nightly jobs, where a single run can touch thousands of records at once. Pass the checkpoint to claim your Bulk Master stamp, then carry on.

Checkpoint

Earn the Bulk Master stamp

Five questions to lock in Module 05.