By configuring a database connection and a SELECT query, Flashduty connects to your database on the schedule you define, incrementally fetches new rows via cursor-based pagination, and converts each row into a Standard Alert Event using field mapping rules. Your system does not need to support push delivery.
:::tips
DB Pull is the right choice when alert data is already stored in a relational database and you cannot or do not want to modify the existing system to support webhook push. If the database is on a network that Flashduty cannot reach, consider exporting alerts to a publicly accessible HTTP endpoint and using the HTTP Pull integration instead.
:::
Setup Steps
In Flashduty
Configuration
Database Driver
| Field | Required | Description |
|---|
| Driver | Yes | The database type. Supported values: mysql, postgres (or postgresql), clickhouse. Case-insensitive — the system normalizes to lowercase. |
Connection
| Field | Required | Description |
|---|
| Host | Yes | Hostname or IP address of the database server. Loopback addresses (127.x.x.x / ::1), private subnets, and link-local addresses are rejected to prevent SSRF attacks. |
| Port | Yes | Database listener port. Common defaults: MySQL 3306, PostgreSQL 5432, ClickHouse 9000. |
| Username | Yes | The account used to connect. A read-only account is strongly recommended. |
| Password | Yes | Connection password, stored encrypted and never shown in plaintext after saving. |
| Database | Yes | Name of the database to connect to. |
| Extra Params | No | Additional connection parameters as key-value pairs, mapped to driver-specific DSN options (e.g., MySQL timeout, PostgreSQL sslmode). |
Query Configuration
| Field | Required | Default | Description |
|---|
| Query | Yes | - | A read-only SELECT statement (or a CTE starting with WITH). DML/DDL keywords (INSERT, UPDATE, DELETE, DROP, etc.) are forbidden. Parameter placeholders (?) are forbidden. Row-limiting keywords (LIMIT, OFFSET, FETCH NEXT, SELECT TOP) are forbidden — the system controls pagination automatically. The query output must include both cursor columns (time_column and id_column); validation fails at save time if they are missing. |
| Timeout (seconds) | Yes | 5 | Maximum execution time for a single page query, range 1 ~ 10 seconds. Values above 10 are clamped to 10. |
| Polling Cycle (seconds) | Yes | - | Interval between successive polling cycles (seconds). |
| Max Pages | Yes | 5 | Maximum pages fetched per polling cycle, range 1 ~ 10. Values above 10 are clamped to 10. Pagination stops when the cap is reached or a page returns fewer rows than page_size. |
| Page Size | Yes | 500 | Maximum rows returned per page, range 1 ~ 1000. Values above 1000 are clamped to 1000. |
The total rows ingested per cycle is bounded by max_pages × page_size and is also subject to a system-wide event count ceiling. Set page_size to a batch size your database can handle efficiently (typically 200–500 rows) and tune max_pages based on your alert throughput.
Cursor Configuration
Flashduty uses keyset pagination to fetch new rows incrementally and avoid full-table scans. After each polling cycle, the system persists the cursor position of the last processed row and resumes from there on the next cycle.
| Field | Required | Description |
|---|
Time Column (time_column) | Yes | The timestamp column used for ordering and pagination. The name must match [a-zA-Z_][a-zA-Z0-9_]* and must appear in the SELECT output. |
ID Column (id_column) | Yes | A unique-identifier column used together with the time column to break ties when multiple rows share the same timestamp (typically an auto-increment primary key or UUID). Same naming rules as time_column. |
Initial Time (initial_time) | No | The starting point for the very first fetch (or after a checkpoint reset), in YYYY-MM-DD HH:MM:SS format. If omitted, the system uses the time the integration was saved as the starting point — rows that already exist before that moment will not be fetched. |
How pagination works
The system wraps your SELECT statement in a subquery and appends keyset conditions, ordering, and a LIMIT on the outer query:
SELECT * FROM (<your query>) AS _src
WHERE (_src.<time_column> > ? OR (_src.<time_column> = ? AND _src.<id_column> > ?))
ORDER BY _src.<time_column> ASC, _src.<id_column> ASC
LIMIT <page_size>
Do not include ORDER BY, LIMIT, or OFFSET in your own query — the system controls these.
Automatic checkpoint reset
The system computes a fingerprint over the fields that define the ordered row stream: driver, host, port, database, query, time_column, id_column, and initial_time. When any of these fields change, the checkpoint is automatically invalidated and the next fetch restarts from initial_time. Editing field mappings or severity mappings does not trigger a checkpoint reset and will not replay historical rows.
Field Mapping
Field mapping controls which database columns (or constant values) are mapped to which fields of the Standard Alert Event.
Standard Field Mapping (fields)
Each mapping rule specifies a target field (a Standard Event field name) and a rule. Three rule types are supported:
| Rule Type | type Value | value Description |
|---|
| Column | column | Reads the value of the named column from the database row directly. Example: "type": "column", "value": "alert_title" reads the alert_title column. |
| Constant | const | A fixed string applied to every row. Example: "type": "const", "value": "Critical" always sets the field to Critical. |
| Template | template | A Go template string that can reference any column in the row. Example: "type": "template", "value": "{{.host}}: {{.message}}" concatenates the host and message columns. |
When the target field is event_time, the system automatically converts the column value to a Unix timestamp in seconds. Supported input formats include time.Time, Unix milliseconds (integer), "2006-01-02T15:04:05", "2006-01-02 15:04:05", and other common datetime representations.
Label Mapping (labels)
Label mapping controls how database columns are converted into the labels dictionary of the alert event. Four modes are supported:
| Mode | mode Value | Description |
|---|
| Specific Columns | include_columns | Only the columns listed in columns are included as labels. The label key is the column name; the label value is the column’s string representation. |
| All Columns | all_columns | Every column in the query result is automatically added as a label, excluding cursor columns and columns already referenced by fields rules. Useful when the column set is small or variable. |
| JSON Column | json_column | Parses the specified column’s value as a JSON object ({"key": "value", ...}) and maps it directly to labels. The column value must be valid JSON. |
| Manual | manual | Explicitly maps label keys to source column names, e.g. {"region": "dc_region", "env": "deploy_env"}. The map key is the label name; the map value is the source column name. |
Severity Mapping
External systems use inconsistent field names and values for alert severity. Severity Mapping translates the external value into Flashduty’s standard Critical / Warning / Info.
- Flashduty reads the
event_status field produced by field mapping and looks it up in the severity mapping table.
- Fallback when no match: if
event_status does not match any key in the table, the severity defaults to Warning.
Example configuration:
{
"P0": "Critical",
"P1": "Critical",
"P2": "Warning",
"P3": "Info"
}
Default Route
When creating a “Shared Integration” (under Integration Center => Alert Events), you must configure a default route — otherwise newly pulled events will be dropped. After creation, you can add finer-grained rules under Route.
A “Dedicated Integration” (created under the Integrations tab of a specific channel) is automatically bound to that channel and does not require a separate default route.
Notes
- Database account permissions: Create a dedicated read-only account for DB Pull with only
SELECT privilege on the target table. Do not grant write access.
- Network reachability: The Flashduty service must be able to reach
host:port over the public internet or a dedicated line. Private subnets (10.x.x.x, 192.168.x.x, 172.16–31.x.x) and loopback addresses are rejected by the system.
- Index on cursor columns: For performance, create a composite index on
(time_column, id_column) to support efficient keyset pagination queries.
- Time column precision: The system records cursor timestamps with microsecond precision (
2006-01-02 15:04:05.999999). Use at least millisecond precision for your time column (DATETIME(3) or TIMESTAMP(6)) to avoid missing rows when many rows arrive within the same second.
- Query idempotency: After a checkpoint reset, the same rows may be fetched again. Ensure your field mapping includes a column that uniquely identifies each alert (mapped to
alert_key) so that Flashduty can correctly deduplicate events.