Private Beta
.md

BountyHub Docs

Datasets Overview

How project datasets store observations, reconcile identity, expose current state and history, and where to query, filter, view, export, and push them.

Datasets overview

A dataset is a project-owned table of observations — subdomains, live hosts, findings, or anything else your workflows collect. Observations are append-only: each push records a new snapshot with an ingest timestamp, and the service derives the current state from the history.

Open a project's Datasets tab to browse the Query, Table, Views, and Notifications surfaces. This page explains the model; the rest of the section covers each surface in depth.

#The model

ConceptMeaning
ObservationOne row pushed with step.update_dataset or IngestDatasetRows.
Ingest timestamp__ingested_at, recorded for every observation.
IdentityThe column(s) that make two observations the same logical record.
Current stateThe latest observation per identity, with stale rows removed.
HistoryEvery observation ever pushed, including superseded ones.
ViewA saved read-only SQL query over project datasets and other views.

#Current state and history

By default, queries run over the current state: for each identity, only the latest observation (by __ingested_at) is returned, and rows marked stale are excluded. A dataset without identity columns has no reconciliation key, so every pushed row is its own record.

Set includeHistory = true (UI: Include history; CLI: --include-history) to run over the raw append-only stream instead. History keeps every observation, including duplicate identities and older versions.

#Reserved columns

Every dataset relation exposes two internal columns in addition to your schema:

ColumnTypeMeaning
__ingested_attimestampWhen the observation was pushed.
__deletedbooleanWhether the record is marked stale. Current-state queries exclude true rows.

Both are reserved names and cannot be added to a dataset schema.

#Removing rows

DeleteDatasetRows removes records selected by a structured filter. mode chooses what happens to the stored observations:

ModeEffect
DATASET_DELETE_MODE_SOFTAppends tombstones for the matching identities. Current-state queries hide the records; history keeps the tombstones and the observations they supersede. Requires identity columns.
DATASET_DELETE_MODE_HARDRewrites stored files to remove every observation belonging to the matching records. History no longer contains them.

ClearDataset removes every record and stored file in the table. Deleting a dataset, clearing it, or hard-deleting rows releases the parquet storage from the account's storage usage; soft deletes and new observations record the bytes they add.

#Pushing observations

Workflows push transform output into an existing dataset. The dataset service owns identity matching, reconciliation, and storage; the workflow supplies only the rows and the mode.

BHW
  • mode = "upsert" updates or creates records matching known identities; identities absent from the push are untouched.
  • mode = "sync" declares the push authoritative: identities absent from the push are marked stale.

See Pushing dataset rows for mapping, transform sources, and a complete asset-tracking workflow.

#Query surfaces

SurfaceRuns overWhere
Single-dataset SQLOne dataset, current state or historyDatasets → Query → Advanced SQL
Structured filtersThe result of the single-dataset queryDatasets → Query → Filters
Saved viewsProject datasets and other views, current state onlyDatasets → Views
Project-wide SQLEvery dataset in a project, current state onlyAPI QueryDatasets
DescribeColumn null counts, distinct counts, top valuesCLI bh dataset describe or API
ExportA full single-dataset query resultDatasets query download or API

The only relations a query may reference are the ones registered for its scope: dataset for a single-dataset query, or the project's dataset names for a project-wide query. File scans, catalog tables, table functions, and other datasets are rejected. See SQL reference for the full policy.

#Dataset notifications

Each dataset can route row changes to email, Discord, or Slack channels from the dataset's Notifications tab. Create the integration and notification channel first, then assign it to the dataset and choose the routes: rows added, removed, or changed. See Notifications overview for channel setup.

#Limits

LimitValue
Datasets per project100
Views per project100
Single-dataset and project-wide page sizeDefault 100, maximum 1,000
Saved-view page sizeDefault 100, maximum 10,000
Row materialization guard (engine)100,000
Query memory2 GB by default
Concurrent interactive queries per user2
Interactive queries per user per minute60
Export download URL lifetime15 minutes

Workflow runners are exempt from the interactive fairness limits; they are bounded by runner capacity instead. Operators can tune the defaults with BOUNTYHUB_HUB_DATASET_QUERY_MAX_ROWS, BOUNTYHUB_HUB_DATASET_QUERY_MEMORY_LIMIT, BOUNTYHUB_HUB_DATASET_QUERY_MAX_CONCURRENT_PER_USER, and BOUNTYHUB_HUB_DATASET_QUERY_PER_MINUTE.

#Next steps