n8n Training Hub
Back to home

The mini CRM with no database

Data Tables

You want to manage a list of event sign-ups without standing up Postgres or Airtable. n8n native Data Tables are enough: add people, avoid duplicates, update the status of those who confirm. In this track you learn to model data and keep its state over time.

Download test data
n8n nodes involved
  • Webhook
  • Data Table
  • IF
  • Edit Fields (Set)
0/5 done
Step B1

Create the table and seed it

Goal

Create a Data Table with the fields email, name, status. Seed it with the 3 initial dataset records (by hand or by importing the CSV).

Done criteria

Get help
Node flow
Data Tablecreate + seed

Data Tables are n8n's own built-in storage, no external database needed. Open the Data tables section of your instance and create one, then define the columns: email (String), name (String), status (String).

Seed the 3 starting rows by hand in that view, or add them from a workflow with a Data Table node set to the Insert operation. Either path leaves you with the same three rows.

Treat email as the key from the start: it is the field that identifies a person uniquely, and the next steps lean on it to find and update people.

Screenshots
Step B2

Receive a new sign-up

Goal

Build a workflow with a Webhook that receives a new sign-up (email, name, status) and inserts it into the Data Table. Use the site Event Sender to send the first new sign-up.

Done criteria

Get help
Node flow
WebhookPOST
Data TableInsert

Add a Webhook trigger set to POST and click "Listen for test event" so you can watch calls arrive. The event lands nested under body, so the fields are {{ $json.body.email }}, {{ $json.body.name }}, {{ $json.body.status }}.

Add a Data Table node, choose your table, and set the operation to Insert. Map each column to its body field. For now just insert, the next step handles duplicates.

Send the first sign-up from the Event Sender below and confirm the new row really lands in the table.

Screenshots
Step B3

Avoid duplicates

Goal

Before inserting, check whether a row with that email already exists. If it does, do NOT create a duplicate (update or skip). From the Event Sender, send the second event, which is anna, an email that is already present.

Done criteria

Get help
Node flow
Webhook
Data TableGet
IF

This is where data modeling starts to bite. Before inserting, run a Data Table node with the Get operation, filtered by email, to see whether that person already exists. Feed the result into an IF node: if a row came back, skip or update; if nothing came back, insert.

There is a shorter path too. The Data Table node offers an Upsert operation that does both at once: it updates the matching row if the email exists, and inserts a new one if it does not. Grasping the difference between Insert, Update and Upsert is the real goal of this step.

Send the anna event from the Event Sender (an email already in the table) and confirm you never end up with two rows sharing one email.

Screenshots

From the n8n docs

Step B4

Update the status (confirmations)

Goal

Handle events of type confirm: find the person by email and change their status from invited to confirmed. From the Event Sender, send the confirmation event for bruno.

Done criteria

Get help
Node flow
Webhook
IFaction
Data TableUpdate

Tell the event types apart first. Each event carries an action field that is either insert or confirm, so branch on it with an IF or a Switch. For a confirmation, run the Data Table node with the Update operation, matching on email, and set status to confirmed.

The interesting case is a confirmation for an email that is not in the table. Look the person up first with Get, then use an IF on whether a row was found: the not-found branch should do nothing or log, never throw. To rehearse safely, the Update and Delete operations even offer a "Dry Run" option that simulates the change without touching the data.

Send bruno's confirmation from the Event Sender, then send the ignoto@mail.it confirmation and check the workflow stays calm. Handling edge cases gracefully is part of modeling data.

Screenshots

From the n8n docs

Step B5Stretch

Count the confirmations

Goal

Add a step that, on demand, counts how many people are confirmed out of the total invited.

Done criteria

Get help
Node flow
Data TableGet all
Aggregatecount

Read the whole table with a Data Table node set to Get (no filter, so it returns every row), then count how many rows have status confirmed against the total.

You can do it natively: an Aggregate node to count items, or an Edit Fields (Set) node with an expression over the returned list. Keep it simple, the point is the shape of the answer, not a fancy query.

It is your first taste of reporting on your own data: turning rows into a number someone actually cares about.

Screenshots

Test tool

Event Sender

Paste your webhook URL and send the dataset events, one at a time or all in sequence. Watch inserts, duplicates, and confirmations arrive in order.

    Paste your webhook URL above first.

    What you sent

    Nothing yet. Send a test call.

    What you got back

    Nothing yet. Send a test call.