> ## Documentation Index
> Fetch the complete documentation index at: https://docs.noxus.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Guidelines for designing, filling, querying and securing tables

Follow these practices to keep your tables reliable, fast and safe to share across flows and agents.

## Designing Tables

| Practice | What to Do | Why It Matters |
| :- | :- | :- |
| **Consider the primary key up front** | Know which of **UUID** or **Auto-increment** you require when you create the table | The primary key type can't be changed later |
| **Name for the identifier** | Choose a short name that reads well in SQL, such as `Orders` rather than `2024 Orders (final)` | The identifier is generated from the name and never changes, even if you rename the table |
| **Discern types before adding rows** | Set column types while the table is empty | Once a table has rows, only Text and Number can be converted |
| **Write a description** | Say what one row represents | Helps teammates, and gives agents and Genie context |

### Choosing a primary key

**Choose UUID (the default) if:**

* IDs shouldn't be guessable or reveal how many rows exist, for example when they appear in links or are shared outside the team.
* You may combine rows from several tables or workspaces later. UUIDs never clash, while auto-increment IDs start at 1 in every table.

**Choose Auto-increment if:**

* People will refer to rows by number, such as order `1042` or ticket `17`.
* You want IDs that show the order rows were added in.
* You'll often type IDs by hand in SQL or filters, where a short number is easier than a UUID.

Auto-increment numbers aren't reused, so deleting rows leaves gaps.

## Importing Data

| Practice | What to Do | Why It Matters |
| :- | :- | :- |
| **Clean the header row** | Use short, unique headers with no `id` column | Headers become column names and identifiers |
| **Check the inferred types** | Review each column's type before importing | Only Number, Boolean and Text are inferred |
| **Split very large files** | Keep each file under 25 MB and 500,000 rows | Larger files are rejected |
| **Fix the reported row** | Correct the row and column named in the error, then retry | Imports are all-or-nothing, so nothing is half-imported |

## Querying

| Practice | What to Do | Why It Matters |
| :- | :- | :- |
| **Always add `LIMIT` and `ORDER BY`** | Say how many rows you want and in what order | Results are capped at 10,000 rows, and order isn't guaranteed without `ORDER BY` |
| **Filter in SQL** | Put conditions in `WHERE` rather than filtering rows later in the flow | Less data moves through the flow, and runs are faster |
| **Use identifiers** | Refer to tables and columns by identifier, not display name | Display names aren't valid in SQL |
| **Keep queries short** | Filter early and avoid unneeded joins | Queries are cancelled after 10 seconds |

## Security

| Practice | What to Do | Why It Matters |
| :- | :- | :- |
| **Treat tables as shared** | Keep data in a table only if everyone in the workspace may see it | Every table is shared with the whole workspace |
| **Keep agent edits off** | Turn on **Allow edits** only for agents that must change a table | Agent writes don't ask for approval |
| **Bind untrusted values** | Use **Insert**, **Update** or **Delete Table Row** for values from users or emails | Query Table pastes variables into the SQL as text |
| **Leave write toggles off** | Turn on Query Table's write toggles only on nodes that need them | A write can't be undone |

## Common Issues and Solutions

<AccordionGroup>
  <Accordion title="Importing" icon="file-up">
    * **`id` column in the file**: `id` is reserved. Rename the column before importing.
    * **Title rows above the header**: check **Header row** points at the real header.
    * **Finding a failed row**: error row numbers count data rows only, so search the file for the quoted value.
  </Accordion>

  <Accordion title="Querying" icon="database">
    * **Display names in SQL**: use the table and column identifiers instead.
    * **Writing from the search bar**: it only reads. Use Query Table, an agent with **Allow edits**, or Genie.
    * **Write toggle off**: turn on the matching toggle under **Advanced options** in Query Table.
    * **Agent `UPDATE` or `DELETE` rejected**: include a `WHERE` clause.
    * **Large results**: add `LIMIT` and `ORDER BY`, as results are capped at 10,000 rows.
  </Accordion>

  <Accordion title="Relationships" icon="link">
    * **Deleting a referenced table**: remove the reference columns that point to it first.
    * **Cascade**: deleting a row also deletes the rows that reference it, so choose it deliberately.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.