Linking AppSignal as a source
Let AI connect your sources for you
Skip the manual setup — run this in your project and the wizard auto-detects your databases and APIs and connects them to PostHog.

This source is currently in alpha. The interface and available tables may change.
The AppSignal connector syncs the monitoring data of one AppSignal app into the PostHog Data Warehouse: incidents, error and performance samples, deploy markers and deploy stats, log lines, metrics, distributed traces, and per-action performance aggregates. You can then join application health to how people use your product, and see the release or the slow action that a drop in usage follows.
Prerequisites
You need a personal API token and the ID of the app you want to sync. The token inherits the permissions of the AppSignal user who created it, so that user needs access to the app.
Each source connects to one app. To sync more than one app, add one source per app.
Adding a data source
- In PostHog, go to the Sources tab of the data pipeline section.
- Click + New source and click Link next to this source.
- Enter your credentials (see Configuration below) and click Next.
- Select the tables you want to sync, choose a sync method and frequency, then click Import.
Once the syncs are complete, you can start querying this data in PostHog.
When linking AppSignal, you'll need:
- Personal API token – find it in your AppSignal personal settings under API key.
- App ID – the identifier in your app's AppSignal URL:
https://appsignal.com/<organization>/sites/<app ID>.
PostHog checks both values when you connect. If AppSignal rejects them, the connection fails immediately.
The app ID is part of the connection. If you change it, you must enter the token again, so that a stored token cannot read another app.
Sync modes
Each table can be synced in one of several modes, depending on what the source supports:
- Webhook (when available) – the source pushes changes to PostHog in real time. Fastest freshness, lowest ongoing cost, and the only mode that reliably captures updates and deletes.
- Incremental – only new or updated rows are synced on each run, using a cursor field (such as an
updated_attimestamp). Cheaper than a full refresh, but deletes aren't captured. - Append only – new rows are appended using a cursor field; existing rows are never updated. Ideal for immutable, append-only tables like event logs.
- Full refresh – the whole table is reloaded on every sync. Use it when a table has no reliable cursor or when you need deletions reflected.
See sync methods for a full explanation of how each mode works and how to choose between them.
The Supported tables section below shows the sync method for each table. In short:
- Tables of records that never change after AppSignal writes them (samples, log lines, traces, spans) are append-only.
- Tables of records that AppSignal keeps updating (deploy markers, metric buckets, deploy stats) merge on their key.
- Incident tables are aggregates whose count, state, and last occurrence keep changing, and the GraphQL API that serves them cannot filter by time, so they are full refresh only. The small lookup tables (
apps,metric_names) are full refresh too.
AppSignal does not report how much history your plan keeps, so the first sync of each metrics, tracing, and deploy-stats table starts from a fixed lookback (7 to 90 days, depending on the table) instead of asking for all of it. The other tables walk your full history, which AppSignal limits to your plan's retention period.
Tables that cost one AppSignal request per item (trace_spans, slow_event_actions, deploy_stats) are capped per run. If your app has more items than the cap, run the sync again and it continues from where it stopped.
Configuration
| Option | Type | Required |
|---|---|---|
Personal API token | password | Yes |
App ID | text | Yes |
Supported tables
| Table | Description | Sync method | Incremental field | Primary key |
|---|---|---|---|---|
exception_incidents | An exception incident: a group of similar errors tracked by AppSignal, with its occurrence count and triage state. | Full refresh | — | — |
performance_incidents | A performance incident: a slow action tracked by AppSignal, with its duration statistics and triage state. | Full refresh | — | — |
anomaly_incidents | An anomaly incident: an alert trigger on a metric firing, with the trigger that opened it and the tags of the matching metric. | Full refresh | — | — |
log_incidents | A log incident: a log line trigger firing, with the trigger's query and the last log line that matched it. | Full refresh | — | — |
deploy_markers | A deploy marker: an application release tracked by AppSignal, with the error rate observed while it was live. | Incremental, Full refresh | created_at | — |
deploy_stats | Throughput, mean response time and error rate for the revision of one deploy marker. | Incremental, Full refresh | created_at | — |
error_samples | An individual error sample: one recorded occurrence of an exception, with request context. | Incremental, Full refresh | time | — |
performance_samples | An individual performance sample: one recorded slow request, with timing breakdown. | Incremental, Full refresh | time | — |
apps | An AppSignal app (site): the lookup that resolves the app ID every other AppSignal table is keyed by, with the organization that owns it. | Full refresh | — | — |
log_lines | A single log line collected by AppSignal log management. Only the Public API V2 serves log lines; the GraphQL API has no field for them. | Incremental, Full refresh | timestamp | — |
metric_names | The metric catalog for an app: one row per metric name, with its type and the tag keys it carries. | Full refresh | — | — |
metric_timeseries | One hourly bucket of one metric series. Covers custom and platform metrics; the GraphQL metrics API is deprecated, so V2 is the supported source. | Incremental, Full refresh | timestamp | — |
performance_traces | A distributed trace recorded for a performance action, summarized at its root span. | Incremental, Full refresh | time | — |
trace_spans | A single span of a distributed trace, with its timing, status and attributes. | Incremental, Full refresh | trace_time | — |
performance_actions | Per-action performance, aggregated into hourly buckets: how often each action ran, how long it took and how often it failed. | Incremental, Full refresh | timestamp | — |
service_edges | One hourly bucket of traffic between this app and a peer service, as seen through distributed tracing. | Incremental, Full refresh | timestamp | — |
slow_events | A slow operation inside traces, such as a slow database query, ranked by its impact over a daily bucket. | Incremental, Full refresh | timestamp | — |
slow_event_actions | An action a slow operation appears in, with an example trace to open. | Incremental, Full refresh | timestamp | — |
metric_timeseries holds one row per metric series per hour, for both custom and platform metrics. Read it together with metric_names, which lists each metric name, its type, and the tag keys it carries.
Troubleshooting
- If you see a 401 error, the token is invalid or was revoked. Copy a new token from your personal settings, then reconnect.
- If you see a 403 error, the AppSignal user who owns the token cannot read this app. Check the token and the app ID, then reconnect.
- If you see a 404 error, or AppSignal app not found, the app ID is wrong. Copy the identifier from your app's AppSignal URL.
- If
log_linesstays empty, the app has no log sources. Check that your app sends its logs to AppSignal. - If a metric is missing from
metric_timeseries, check thatmetric_nameslists it. The connector syncs gauge, counter, and measurement metrics, and skips a metric of any other type. - If
trace_spanslags behindperformance_traces, the sync reached the per-run trace limit. Increase the sync frequency until the table catches up.
If your sync is failing or data looks wrong, see the Data warehouse troubleshooting guide. If that doesn't help, contact support – we're happy to help.