# pointblank, data validation and a data dictionary in one R package

> pointblank is an R package that validates data frames and database tables with a large set of composable validation functions, and separately maintains the metadata that describes those tables so the documentation does not go stale. The design point is that the same checks run either against a local frame or entirely inside the database.

**rstudio/pointblank** — Data quality assessment and metadata reporting for data frames and database tables

- Repository: https://github.com/rstudio/pointblank
- Website: https://rstudio.github.io/pointblank/
- Stars: 1,054 · Forks: 63
- Language: R
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/rstudio-pointblank

## Two objects, two jobs

With the pointblank package it is really easy to methodically validate your data whether in the form of data frames or as database tables, and on top of the validation toolset the package gives you the means to provide and keep up-to-date with the information that defines your tables.

The design is two object types that solve two separate problems, and keeping them apart is the main structural idea in the package.

The agent object is for table validation. It works with a large collection of simple, yet powerful, validation functions, and it can be made considerably more sophisticated through custom expressions, segmenting the data, and selective mutations of the target table. The suite of validation functions ensures that everything just works no matter whether your table is a data frame or a database table.

The informant object is for table information, the metadata entries, and the associated functions help define them and present the result as a data dictionary. The point is stated clearly: just like with validation, pointblank offers easy ways to have the metadata updated so that this important documentation does not become stale.

That second problem is the one most data teams have and rarely solve. A data dictionary that lives in a wiki and describes a table that has since changed is worse than no dictionary, because people trust it. An informant that is regenerated from the table is a different kind of artefact.

The package is available on CRAN, the documentation site is rstudio.github.io/pointblank, and the release tags are v0.12.4 from 2026-07-21, v0.12.3 from 2025-11-28 and v0.12.2 from 2024-10-23, with the last push on 2026-08-21.

## The validation workflow, as the README writes it

The README walks through a complete example, and it is worth following because the shape of the API becomes clear from it.

``` r
# Generate a simple `action_levels` object to
# set the `warn` state if a validation step
# has a single 'fail' test unit
al <- action_levels(warn_at = 1)

# Create a pointblank `agent` object, with the
# tibble as the target table. Use three validation
# functions, then, `interrogate()`. The agent will
# then have some useful intel.
agent <- 
  dplyr::tibble(
    a = c(5, 7, 6, 5, NA, 7),
    b = c(6, 1, 0, 6,  0, 7)
  ) %>%
  create_agent(
    label = "A very *simple* example.",
    actions = al
  ) %>%
  col_vals_between(
    columns = a,
    left = 1,
    right = 9,
    na_pass = TRUE
  ) %>%
  col_vals_lt(
    columns = c, 12,
    preconditions = ~ . %>% dplyr::mutate(c = a + b)
  ) %>%
  col_is_numeric(columns = c(a, b)) %>%
  interrogate()
```

Four things happen in that chain. The action_levels object sets what should happen when a step fails, and warn_at = 1 means a single failing test unit moves the step into the warn state. create_agent takes the target table and the actions. Then the validation functions are chained on, and each one is a step in the validation plan. And interrogate runs the plan.

The validation functions themselves show the range. col_vals_between checks that a column's values fall in a range, with na_pass = TRUE deciding how missing values are treated. col_is_numeric checks a column's type. And the preconditions argument is the interesting one, because it shows how a derived column is created for the check: the c column does not exist in the tibble, and the precondition mutates the data with dplyr::mutate(c = a + b) before the check runs on it.

That precondition mechanism is how you express a check against a value that is not stored, and it is a common requirement in real data validation where the interesting property is a relationship between columns rather than a single column's values.

Once interrogate has run, printing the agent produces a gt-based report, which is the point of the whole design. The README's verdict is that the reporting is pretty sweet, and the report is what turns a validation run into something you can send to someone.

## Local frames, database tables and Spark, with the same checks

The performance claim is stated in the README and it is a specific one. The package is designed to be both straightforward yet powerful, and fast. Local data frames don't take very long to validate extensively, and all validation checks on remote tables are done entirely in-database. So you can add dozens or even hundreds of validation steps without any long waits for reporting.

The mechanism for the remote case is a different backend rather than a different API. If you want to perform validation checks on database or Spark tables, you provide a tbl_dbi or tbl_spark object to create_agent. The same validation functions then run inside the database.

The supported backends are named explicitly, and the primary one is PostgreSQL. Also MySQL, MariaDB, Microsoft SQL Server, Google BigQuery, DuckDB, and Spark DataFrames through the sparklyr package.

That list is worth reading as a compatibility matrix rather than a feature list, because the fact that the checks are pushed into the database is what makes a hundred validation steps practical against a large table, and the fact that the backend list is finite is what determines whether your warehouse is supported.

The README shows sample validation reports for the considerably larger nintendo::nintendo_revenue table, with published reports for PostgreSQL, MySQL and DuckDB, which is a useful way to see what the output looks like at a scale where a local frame would not be practical.

The Data Quality Reporting workflow is the scheduled counterpart to this. Data validation can be carried out in that workflow, ultimately resulting in the production of a data quality analysis report, and it is most useful in a non-interactive mode where data quality for database tables and on-disk data files must be periodically checked. The agent is given a collection of validation functions to define validation steps, and you can get extracts of data rows that failed validation, set up custom functions that are invoked by exceeding set threshold failure rates, and email the report regularly, or only if certain conditions are met.

## Pipeline validation, where the checks are a filter

The second workflow is the one most ETL pipelines need, and it works differently in a way that is easy to miss from the agent API.

The Pipeline Data Validation workflow uses the same collection of validation functions but without the need of an agent. The README describes it as useful for an ETL process where you want to periodically check data and trigger warnings, raise errors, or write out logs when exceeding specified failure thresholds. It is a cinch to perform checks on import of the data and at key points during the transformation process, perhaps stopping data flow if things are unacceptable with regard to data quality.

The key difference is that the validation functions act as a filter, passing data through unless execution is stopped by failing validations beyond the set threshold.

That is a different contract from the agent, and it is the more useful one for a pipeline. The agent collects failures and reports on them. The pipeline version gates the data. A row that fails a check is either dropped, or it raises an error, or the run logs and continues, depending on the action levels. So the same function that reports in a quality report becomes a guard in a pipeline, and the choice of action level is what determines whether a bad row stops the job.

This is also why the action_levels object appears in both workflows. It is the shared mechanism, and understanding it is the prerequisite for using either.

The package layout reflects the R package conventions and adds the things a data tool needs. There is R/ for the code, man/ for the Rd documentation, inst/ for installed files, tests/ with testthat, vignettes/ for the long-form guides, pkgdown/ for the documentation site, data/ and data-raw/ for the bundled example data, scripts/ and a .lintr configuration for the linter, a NEWS.md for the changelog, a CITATION.cff and codemeta.json for citation metadata, and an .Rbuildignore for the package build.

The badges in the README header show a project with mature process: R CMD check, a separate lint workflow, codecov coverage, the best practices badge from the core infrastructure project, a repostatus badge marking the project as active, monthly and total CRAN download counts, and a Posit Cloud test drive.

## Conclusion

pointblank suits a data team that wants validation steps written once and run against local frames, database tables and Spark alike, and it suits teams that have let their data dictionary drift out of date, since the informant object exists to keep it in step with the data. It is the wrong choice if you want a test framework, because a validation agent is not a test suite and does not fail a build in the way that testthat does, and it is the wrong choice if your checks need arbitrary procedural logic, because the expression system is a DSL rather than a general language. Before adopting it, check which backends your team actually uses, since the supported list is specific, and look at the action levels, because the default behaviour of a failing step is to report rather than to stop.

## FAQ

### What is pointblank used for?

It is an R package for methodically validating data whether it is in data frames or database tables, and for maintaining the metadata that defines those tables so it can be presented as a data dictionary that does not go stale. It offers an agent object for validations and an informant object for table information.

### How do I run a validation with pointblank?

Create an action_levels object to say what a failure should trigger, pass the target table to create_agent, chain the validation functions such as col_vals_between and col_is_numeric, and call interrogate to run the plan. Printing the agent then produces a gt-based validation report.

### Which databases does pointblank support?

Provide a tbl_dbi or tbl_spark object to create_agent and the checks run in-database. PostgreSQL is the primary supported backend, with MySQL, MariaDB, Microsoft SQL Server, Google BigQuery, DuckDB and Spark DataFrames through sparklyr also supported.

### What is the difference between the agent and the pipeline workflows?

The agent workflow collects failures and reports on them, which suits non-interactive scheduled checks. The pipeline workflow uses the same validation functions as a filter, passing data through unless execution is stopped by failing validations beyond the set threshold, which suits ETL steps that should stop on bad data.

### What are action levels in pointblank?

They define what happens when a validation step fails. In the README example action_levels(warn_at = 1) sets the warn state if a validation step has a single fail test unit, and the same object is used in both the agent and the pipeline workflow, so it is the shared mechanism for turning a failure into a warning, an error or a stop.

## Sources

- [Issues](https://github.com/rstudio/pointblank/issues)
- [Project website](https://rstudio.github.io/pointblank/)
- [README](https://github.com/rstudio/pointblank/blob/main/README.md)
- [Releases](https://github.com/rstudio/pointblank/releases)
- [rstudio/pointblank on GitHub](https://github.com/rstudio/pointblank)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rstudio-pointblank
