n8n-data-tables
n8n Data Tables
Data Tables are n8n's built-in tabular storage: real tables inside the n8n instance with columns, types, rows, and CRUD via the dataTable node and data-table MCP tools.
Use them for local persistent state: lookup tables, recent events, per-session inventories, counters, idempotency tracking, dedup state when there's row-level logic or external visibility (plain "have I seen this value?" dedup belongs in the Remove Duplicates node). Small-to-moderate volume (tens of thousands of rows fine, millions belong in a real DB).
Non-negotiables
- System-managed columns + external IDs. Three columns auto-exist on every table:
id(bigserial),createdAt,updatedAt. Don't declare them increate_data_table(errors or shadows the system column). Don't write them on insert. For domain identifiers from outside (arxivId, stripeCustomerId, requestId), add a separate column and key dedup/lookup on that. - Only primitives in columns, nested data uses
string+_objectpostfix. No JSON/object/array column types exist. For nested data (arrays, parsed objects), use astringcolumn withJSON.stringify(...)on write andJSON.parse(...)on read. Mark the column with_object(e.g.,keyInsights_object). The postfix is the contract that tells readers to parse. Seereferences/SCHEMA_DESIGN.md.
Strong defaults
- Don't add a Set node before a Data Table node to modify fields. The Data Table node's per-column expression slots are just as powerful as Set fields, so the Set node is doing zero work the Data Table node can't do itself. (Same Set-node antipattern called out in
n8n-expressions.) - Match n8n's column casing: camelCase. The auto-managed columns are camelCase (
createdAt,updatedAt), so user columns read more cleanly when they match:arxivId,paperId,taxRate. Mixed casing in the same query (createdAt >= ... AND arxiv_id eq ...) reads as a typo. Keep the_objectpostfix on stringified-blob columns regardless (keyInsights_object), the underscore is a contract marker, not casing.
- Verify the
columnsparameter viaget_workflow_detailsafter create/update. The UI has a display quirk in manual mapping mode ("Currently no items exist" with no actual data loss). Checking the JSON confirms what's persisted. - Relational design works when the shape calls for it. For genuine parent-child data (papers → summaries, customers → orders), reference parents by
id, name columns explicitly (paperId,customerId), and enforce integrity in workflow logic. Don't force it on flat use cases (dedup, lookup, audit) where there's no relationship to model. - Storage format is not interface format. Parse
_objectfields before returning them from a sub-workflow. Callers should never receive stringified shells they have to parse themselves. Seereferences/SCHEMA_DESIGN.md"Storage format ≠ interface format".
More from n8n-io/skills
n8n-loops
Use when working with multi-item data, batches, paginated APIs, rate-limited APIs, anything that needs to "do this for each", or any time the user mentions looping, iterating, batching, paging, or "loop over items". Triggers on "loop", "iterate", "for each", "batch", "page through", "paginate", "rate limit", "process all", or any node that should run once vs once-per-item.
5n8n-connections
Use when writing or reviewing n8n SDK code that wires IF, Switch, Merge, error outputs, or any multi-input/multi-output connection. Triggers on .add(), .to(), .input(n), .output(n), .onTrue, .onFalse, .onCase, .onError, useDataOfInput, merge, switch, IF nodes, error branches, fan-out, fan-in, or any review of the workflow's connections object.
3n8n-expressions
Use when writing or reviewing n8n expressions (`{{...}}` syntax), `$json` / `$node` references, Luxon date code, or expression errors. Triggers on `{{}}`, `$json`, `$node`, `$input`, `DateTime`, `Luxon`, "expression error", "evaluating", "format date", "transform field", or any node-parameter assignment.
3n8n-debugging
Use when an n8n workflow isn't working, errors appear, results don't match what was expected, or the user says "this isn't working." Triggers on errors, unexpected output, "it's not working", "why is this happening", "the workflow stopped", failure investigation, or any debugging context.
3n8n-code-nodes
Use when the user reaches for a Code node, mentions writing JavaScript or Python in n8n, or any custom logic comes up in workflow design. Triggers on "Code node", "Code", "JavaScript", "Python", "custom logic", "transform data", "$input", "$json transformation", "loop in code", "write a function", or any time the obvious answer seems to be "just put it in code.
3n8n-binary-and-data
Use when handling files, images, attachments, or binary data in n8n, OR when an AI agent needs to take a user-uploaded file as tool input or return a generated file. For Data Tables (schemas, dedup, persistent state), see the separate n8n-data-tables skill. Triggers on "file", "image", "PDF", "attachment", "binary", "upload", "download", chat trigger with files, agent tool that needs a file, vision/multimodal, or any handling of non-JSON file data.
3