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

# Run conditions

> Control which rows get enriched using conditional expressions.

Run conditions are expressions that Databar evaluates for every row before running an enrichment. If the expression returns **true**, the row is processed. If it returns **false**, the row is skipped.

<Frame>
  <video muted loop playsInline controls preload="metadata">
    <source src="https://mintcdn.com/databar/FvRK3AtZWjIE7Box/images/product-guide/run-conditions-demo.mp4?fit=max&auto=format&n=FvRK3AtZWjIE7Box&q=85&s=645e69ac688ee5f71691e05842931497" type="video/mp4" data-path="images/product-guide/run-conditions-demo.mp4" />
  </video>
</Frame>

This gives you two advantages:

* **Better data quality**: only enrich rows that meet your criteria, so you don't waste processing on irrelevant data.
* **Lower cost**: skipped rows do not consume credits.

## Generate with AI

You don't need to learn CEL syntax to use run conditions. Databar includes a built-in AI generator that writes the expression for you. Just describe what you want in plain English and the AI will produce the corresponding formula.

For example, type "only run on rows where the country is US and the company has more than 50 employees" and the AI will generate `{country} == "US" && {employee_count} >= 50`.

<Tip>
  You can also use LLMs like ChatGPT or Claude to help write CEL expressions. Just describe your table columns and the filtering logic you need.
</Tip>

## Syntax basics

Run conditions are written using **CEL (Common Expression Language)**, an open expression language created by Google. To reference a column in your table, type `{` and select the column name.

```
{country} == "US" && {employee_count} >= 50
```

The expression above runs the enrichment only for US-based companies with 50 or more employees.

## Operator reference

### Comparison operators

| Operator | Meaning               | Example                  |
| -------- | --------------------- | ------------------------ |
| `==`     | Equal to              | `{country} == "US"`      |
| `!=`     | Not equal to          | `{status} != "inactive"` |
| `>`      | Greater than          | `{lead_score} > 80`      |
| `<`      | Less than             | `{employee_count} < 500` |
| `>=`     | Greater than or equal | `{revenue} >= 1000000`   |
| `<=`     | Less than or equal    | `{founded_year} <= 2010` |

### Combining multiple conditions

Use logical operators to chain multiple conditions together in a single run condition expression.

| Operator | Meaning                                 | Example                                                              |
| -------- | --------------------------------------- | -------------------------------------------------------------------- |
| `&&`     | AND: all conditions must be true        | `{country} == "US" && {employee_count} >= 50`                        |
| `\|\|`   | OR: at least one condition must be true | `{title} == "CEO" \|\| {title} == "CTO"`                             |
| `!`      | NOT: exclude rows matching a condition  | `!{website}.contains("test")`                                        |
| `( )`    | Group conditions together               | `({country} == "US" \|\| {country} == "CA") && {revenue} >= 1000000` |

### Text operators

| Operator            | Meaning                      | Example                            |
| ------------------- | ---------------------------- | ---------------------------------- |
| `.contains("x")`    | True if text contains "x"    | `{email}.contains("@gmail.com")`   |
| `.startsWith("x")`  | True if text starts with "x" | `{phone}.startsWith("+1")`         |
| `.endsWith("x")`    | True if text ends with "x"   | `{domain}.endsWith(".io")`         |
| `.size()`           | Number of characters         | `{email}.size() > 0`               |
| `.matches("regex")` | Regex match                  | `{email}.matches("^.+@.+\\..+$")`  |
| `.lowerAscii()`     | Convert to lowercase         | `{country}.lowerAscii() == "us"`   |
| `.upperAscii()`     | Convert to uppercase         | `{code}.upperAscii() == "USA"`     |
| `+`                 | Join text                    | `{first_name} + " " + {last_name}` |

### Math operators

| Operator | Meaning            |
| -------- | ------------------ |
| `+`      | Addition           |
| `-`      | Subtraction        |
| `*`      | Multiplication     |
| `/`      | Division           |
| `%`      | Modulo (remainder) |

### List operators

| Operator                | Meaning                    | Example                                      |
| ----------------------- | -------------------------- | -------------------------------------------- |
| `"x" in list`           | True if "x" is in the list | `"VIP" in {tags}`                            |
| `.size()`               | Number of items            | `{tags}.size() > 0`                          |
| `.exists(x, condition)` | At least one item matches  | `{tags}.exists(t, t.contains("enterprise"))` |
| `.all(x, condition)`    | Every item matches         | `{tags}.all(t, t != "")`                     |

### Handling empty values

| Operator       | Meaning                        | Example                                          |
| -------------- | ------------------------------ | ------------------------------------------------ |
| `has(column)`  | True if the column has a value | `has({email}) && {email}.contains("@gmail.com")` |
| `column != ""` | True if not empty text         | `{email} != ""`                                  |

<Warning>
  Always check for empty values before calling text operators like `.contains()` or `.startsWith()`. Calling these on an empty cell can cause unexpected behavior.
</Warning>

## Examples

### Simple conditions (single rule)

| Goal                 | Expression                       |
| -------------------- | -------------------------------- |
| Only Gmail addresses | `{email}.contains("@gmail.com")` |
| High-scoring leads   | `{lead_score} > 80`              |
| US-based companies   | `{country} == "US"`              |
| Skip empty emails    | `{email} != ""`                  |
| VIP-tagged contacts  | `"VIP" in {tags}`                |
| Skip test websites   | `!{website}.contains("test")`    |

### Combining two conditions

| Goal                             | Expression                                                |
| -------------------------------- | --------------------------------------------------------- |
| US companies with 50+ employees  | `{country} == "US" && {employee_count} >= 50`             |
| Active leads with high scores    | `{status} == "active" && {lead_score} > 80`               |
| Email present and valid format   | `{email} != "" && {email}.contains("@")`                  |
| CEOs or CTOs only                | `{title} == "CEO" \|\| {title} == "CTO"`                  |
| High revenue or Series B funding | `{revenue} >= 5000000 \|\| {funding_stage} == "Series B"` |

### Combining three conditions

| Goal                                 | Expression                                                                                  |
| ------------------------------------ | ------------------------------------------------------------------------------------------- |
| C-level execs at large US companies  | `{country} == "US" && {employee_count} >= 500 && {title}.contains("Chief")`                 |
| US or Canada, 50+ employees          | `({country} == "US" \|\| {country} == "CA") && {employee_count} >= 50`                      |
| Active enterprise leads with email   | `{status} == "active" && {plan} == "enterprise" && {email} != ""`                           |
| Skip test, demo, and example domains | `!{domain}.contains("test") && !{domain}.contains("demo") && !{domain}.contains("example")` |

### Combining four or more conditions

| Goal                                            | Expression                                                                                                                                                           |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Enterprise targets in North America with budget | `({country} == "US" \|\| {country} == "CA") && {employee_count} >= 200 && {revenue} >= 1000000 && {status} == "active"`                                              |
| Qualified SaaS leads                            | `{industry} == "SaaS" && {employee_count} >= 50 && {lead_score} > 70 && has({email})`                                                                                |
| Senior decision-makers at funded companies      | `({title}.contains("VP") \|\| {title}.contains("Director") \|\| {title}.contains("Chief")) && {funding_stage} != "" && {employee_count} >= 100 && {country} == "US"` |

## Tips

<AccordionGroup>
  <Accordion title="Test on a small batch first">
    Before running an enrichment with a new condition across thousands of rows, use the **Run single row** option or filter your table to a small subset. This lets you verify the condition behaves as expected without spending credits.
  </Accordion>

  <Accordion title="Use parentheses to be explicit">
    When mixing `&&` and `||`, wrap groups in parentheses so the evaluation order is clear. Without parentheses, `&&` binds more tightly than `||`, which can produce unexpected results.

    ```
    // Ambiguous
    {country} == "US" || {country} == "CA" && {revenue} >= 1000000

    // Clear
    ({country} == "US" || {country} == "CA") && {revenue} >= 1000000
    ```
  </Accordion>

  <Accordion title="Check for empty values">
    Use `has({column})` or `{column} != ""` before operating on a column that might be empty. This prevents errors from calling `.contains()` or `.startsWith()` on a null value.
  </Accordion>

  <Accordion title="Mind your types">
    CEL is type-aware. If a column stores numbers as text, you may need to convert with `int()` before comparing:

    ```
    int({employee_count}) >= 50
    ```

    Similarly, text comparisons are case-sensitive by default. Use `.lowerAscii()` to normalize.
  </Accordion>

  <Accordion title="Skipped rows are free">
    Rows that fail a run condition are not sent to the data provider and do not consume credits. Use conditions aggressively to keep costs predictable.
  </Accordion>
</AccordionGroup>

## FAQ

<AccordionGroup>
  <Accordion title="Can I use multiple run conditions?">
    Yes. You combine multiple conditions in a single expression using `&&` (AND) and `||` (OR) operators. For example, `{country} == "US" && {employee_count} >= 50 && {email} != ""` checks three conditions at once. There is no limit to how many conditions you can chain together. See [Combining multiple conditions](#combining-multiple-conditions) for the full syntax.
  </Accordion>

  <Accordion title="Do skipped rows cost credits?">
    No. Rows that fail a run condition are never sent to the data provider and do not consume any credits.
  </Accordion>

  <Accordion title="Can I use run conditions with waterfalls?">
    Yes. Run conditions work with both single enrichments and [waterfalls](/product-guide/waterfalls). The condition is evaluated before the waterfall starts, so skipped rows don't trigger any providers.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Enrichments" icon="wand-magic-sparkles" href="/product-guide/enrichments">
    Learn how to add and run enrichments on your tables.
  </Card>

  <Card title="Automations" icon="clock" href="/product-guide/automations">
    Combine run conditions with scheduled or event-driven automation.
  </Card>
</CardGroup>
