Apache Superset Annotations: Marking Events on Time-Series Charts
Learn how to use Apache Superset annotations to mark deployments, incidents, and campaigns on time-series charts. Complete technical guide with examples.
Understanding Apache Superset Annotations
Annotations in Apache Superset are metadata layers that overlay contextual events onto your time-series visualizations. Rather than staring at a flat line chart wondering why metrics spiked or dropped, annotations let you mark exactly what happened and when—a deployment, an incident, a marketing campaign, a database migration, or any other event that explains the data movement.
For data and engineering leaders managing production analytics, this is the difference between a dashboard that tells a story and one that raises more questions than it answers. When your conversion rate drops 15% on a Tuesday afternoon, an annotation immediately shows whether that coincided with a production deployment, a payment processor outage, or a scheduled maintenance window. Without annotations, you’re left digging through logs and Slack threads to reconstruct what happened.
Annotations work by binding events to specific timestamps (or time ranges) and displaying them directly on your chart. They appear as vertical lines, colored bands, or labeled markers depending on the annotation type and your visualization configuration. The key insight: annotations transform dashboards from passive reporting tools into active incident investigation and hypothesis-testing platforms.
Why Annotations Matter for Time-Series Analytics
Time-series data is inherently contextual. A metric’s value only becomes meaningful when you understand what was happening in your system at that moment. Consider a typical mid-market SaaS company:
- Engineering teams deploy code multiple times per day. Without annotations, they can’t correlate performance regressions to specific deployments.
- Operations teams manage infrastructure incidents, database failovers, and scaling events. These events leave fingerprints in metrics—if you can mark them.
- Product teams run experiments, feature launches, and marketing campaigns. Annotations let them measure impact in real time.
- Finance and leadership need dashboards showing KPIs alongside major business events: funding announcements, acquisitions, market shifts, or competitive moves.
The alternative is manual correlation: someone notices a metric anomaly, then spends 30 minutes searching logs, Slack, and Git history to figure out what changed. Multiply that across dozens of dashboards and hundreds of engineers, and you’re looking at thousands of hours of wasted investigative work per year.
Annotations compress that investigation into a glance. When you build dashboards with annotations as a first-class feature, you’re encoding institutional knowledge directly into your analytics layer.
Types of Annotations in Apache Superset
Apache Superset supports two primary annotation types, each serving different use cases:
Event Annotations
Event annotations mark a specific point in time—a discrete moment when something happened. They appear as vertical lines or markers on your chart. Common use cases include:
- Deployments: Mark when code was pushed to production. If a metric shifts immediately after, you’ve found your culprit.
- Incidents: Flag when an outage, error spike, or service degradation occurred.
- Marketing events: Launch dates, campaign starts, promotional offers.
- External events: A competitor announcement, regulatory change, or market event that affects your metrics.
Event annotations are typically sourced from event tables in your data warehouse. For example, a deployments table with columns like deployment_id, timestamp, service_name, and deployed_by. Or a marketing_events table tracking campaign launches, email sends, or paid ad starts.
Interval Annotations
Interval annotations span a time range—they mark a period during which something was happening. These appear as shaded bands or colored regions on your chart. Use cases include:
- Maintenance windows: Database maintenance, infrastructure upgrades, or system migrations that lasted several hours.
- A/B test periods: Mark when an experiment was running so you can measure the impact on metrics over that window.
- Seasonal events: Holiday periods, back-to-school season, or other multi-day events that affect user behavior.
- On-call rotations: Highlight periods when a team was under increased load or managing an incident.
Interval annotations require both a start and end timestamp, allowing you to visualize the duration and impact of extended events.
Setting Up Annotations: The Technical Foundation
To use annotations in Apache Superset, you need to configure them at the chart level. The process involves three steps: creating an annotation layer, configuring the data source, and binding it to your visualization.
Step 1: Create an Annotation Layer
In Superset, you access annotation configuration through the chart editor. Navigate to your time-series chart, click Edit Chart, then look for the Annotations section (typically in the right sidebar or under Advanced options).
You’ll see options to add a new annotation layer. Click Add Annotation Layer and you’ll be prompted to:
- Name the layer: Something descriptive like “Deployments” or “Production Incidents”.
- Choose the annotation type: Event or Interval.
- Select the source: This is where you point Superset to your data.
Step 2: Configure the Data Source
Annotations can be sourced from:
- Database tables: A native table in your data warehouse containing event data.
- Google Sheets: For lightweight, non-technical users to maintain annotation data.
- Superset datasets: If you’ve already created a Superset dataset that aggregates event data.
When configuring the source, you map columns from your table to Superset’s annotation schema:
- Time column: The timestamp field (required). For events, this is when the event occurred. For intervals, this is the start time.
- End time column (intervals only): When the interval ended.
- Title/Label column: The text that appears on the annotation (e.g., “Deploy v2.4.1” or “Database migration”).
- Description column (optional): Longer text that appears on hover, providing context.
- Color column (optional): If you want different annotation types to have different colors, map a categorical column here.
For example, if your deployments table has columns created_at, service, and version, you’d map:
- Time column →
created_at - Title →
CONCAT(service, ' - v', version)or a pre-computed column - Description →
versionor deployment notes
Step 3: Bind to Your Chart
Once the annotation layer is configured, Superset automatically overlays it on any chart that shares the same time dimension. The key requirement: your chart’s x-axis must be a time field, and that time field must be compatible with the annotation’s time column.
For example, if your chart shows hourly revenue (x-axis: order_created_at at hourly granularity) and your annotation layer uses deployment_created_at, Superset will align deployments to the nearest hour on your chart.
Building Annotation Data Pipelines
Annotations are only useful if your data is current and accurate. This means building reliable pipelines that feed events into your annotation tables.
Sourcing Deployment Events
For deployment annotations, you need to capture every production deployment. This typically comes from:
- CI/CD logs: Tools like GitHub Actions, GitLab CI, or Jenkins log every deployment. You can stream these to your data warehouse.
- Deployment services: Platforms like Datadog, New Relic, or Honeycomb have deployment tracking APIs. Query these APIs periodically and load results into a
deploymentstable. - Git webhooks: GitHub, GitLab, and Bitbucket support webhooks that fire on push events. Wire these to a Lambda or Cloud Function that logs to your warehouse.
A minimal deployment table schema:
deployment_id (UUID)
service_name (VARCHAR)
environment (VARCHAR) -- 'production', 'staging', etc.
deployed_at (TIMESTAMP)
deployed_by (VARCHAR)
commit_hash (VARCHAR)
release_version (VARCHAR)
For teams using dbt (data build tool), you can create a dbt model that unions deployments from multiple sources, deduplicates, and enriches them with additional context.
Sourcing Incident Events
Incident data typically comes from:
- Incident management platforms: PagerDuty, Opsgenie, or FireHydrant APIs expose incident creation, resolution, and escalation times.
- Monitoring and alerting: Datadog, New Relic, and Prometheus can trigger webhooks when alerts fire. Log these to a table.
- Manual entry: For critical incidents, ops teams might manually log them in a Slack channel or form. Periodically sync these to your warehouse.
A minimal incidents table:
incident_id (UUID)
incident_title (VARCHAR)
service_affected (VARCHAR)
severity (VARCHAR) -- 'critical', 'high', 'medium', 'low'
detected_at (TIMESTAMP)
resolved_at (TIMESTAMP)
root_cause (VARCHAR, nullable)
Sourcing Campaign and Marketing Events
Marketing events are often easier to track because they’re planned:
- Campaign management platforms: HubSpot, Marketo, or Klaviyo track email sends, ad launches, and campaign dates.
- Product analytics: Segment, Mixpanel, or Amplitude can log custom events for feature launches or experiments.
- Manual spreadsheets: For smaller teams, a Google Sheet with campaign dates can be synced to your warehouse via Superset’s native Google Sheets support.
A minimal campaigns table:
campaign_id (UUID)
campaign_name (VARCHAR)
campaign_type (VARCHAR) -- 'email', 'paid_ads', 'feature_launch', etc.
start_date (TIMESTAMP)
end_date (TIMESTAMP)
description (VARCHAR)
Practical Examples: Annotations in Action
Example 1: Tracking Deployments on a Revenue Chart
Imagine you’re the VP of Engineering at a mid-market SaaS company. Your revenue dashboard shows daily revenue over the past 90 days. Lately, revenue has been trending up—but you want to understand which deployments drove that growth.
You create an event annotation layer sourced from your deployments table, filtering to environment = 'production' and service = 'billing-service'. You map:
- Time column →
deployed_at - Title →
CONCAT('v', release_version, ' by ', deployed_by) - Color → A fixed color (e.g., blue for deployments)
Now, when you view your revenue chart, you see vertical blue lines at each deployment. Immediately, you notice that revenue jumped the day after you deployed the new pricing model (v2.3.0). That’s not coincidence—it’s evidence. You can now correlate that specific feature to business impact.
Better yet, you can share this dashboard with the product and finance teams. They see the same chart, with deployments marked, and can have data-driven conversations about what drove growth.
Example 2: Incident Tracking on a System Health Dashboard
You’re managing an infrastructure dashboard that shows CPU utilization, memory usage, and request latency across your fleet. Last week, you experienced a database outage that lasted 45 minutes.
You create an interval annotation layer sourced from your incidents table. You map:
- Time column →
detected_at - End time column →
resolved_at - Title →
incident_title - Description →
root_cause - Color → Red (for critical incidents)
Now, when you view your latency chart, you see a red band spanning 3:15 PM to 4:00 PM last Tuesday. Hovering over it shows “Database failover - replication lag” as the root cause. Your team can immediately see the correlation between the incident and the latency spike.
This is invaluable for post-mortems: you have a permanent, timestamped record of what happened and when. And when similar patterns emerge in the future, you can reference this historical annotation to guide your investigation.
Example 3: A/B Test Windows on a Conversion Rate Chart
Your product team is running an experiment: a new checkout flow. The test runs for two weeks (July 1-14). You want to measure its impact on conversion rate.
You create an interval annotation layer with:
- Time column →
test_start_date(July 1) - End time column →
test_end_date(July 14) - Title → “Checkout Flow Experiment”
- Color → Green (for experiments)
On your conversion rate chart, you see a green band spanning those two weeks. Within the band, conversion rate rises from 2.1% to 2.4%—a meaningful lift. Outside the band, the rate stays flat at 2.1%. The annotation makes the causal relationship visually obvious.
When you present this to leadership, the chart speaks for itself. No need to explain what the band represents—it’s right there, annotated.
Advanced Annotation Techniques
Dynamic Annotations with Filters
Superset allows you to filter annotation layers by dashboard or chart filters. For example, if your dashboard has a “Service” filter, you can configure your deployment annotation layer to only show deployments for the selected service.
This keeps charts clean and focused. A revenue chart for the “payment-service” only shows payment service deployments, not deployments from the “notifications-service” or “analytics-service”.
Combining Multiple Annotation Layers
You can stack multiple annotation layers on a single chart. For instance, a system health dashboard might show:
- Blue event annotations for deployments
- Red event annotations for incidents
- Yellow interval annotations for maintenance windows
This multi-layered approach tells a complete story: you can see which deployments preceded incidents, which incidents overlapped with maintenance, and how the system responded to each.
However, be cautious about over-annotating. Too many layers can clutter a chart and make it harder to read. Start with 2-3 layers and add more only if they provide clear value.
Annotations with Custom SQL
For advanced use cases, you can source annotations from custom SQL queries rather than simple table selections. This allows you to:
- Aggregate events: If you have millions of individual log entries, query them to find the first error, the peak load, or the longest duration.
- Enrich events: Join deployment data with Git metadata, incident data with on-call rotation data, or campaign data with spend and impressions.
- Filter dynamically: Use dashboard filters in your annotation query to show only relevant events.
For example, a query like:
SELECT
deployed_at,
CONCAT(service_name, ' v', release_version) AS title,
CONCAT('Deployed by ', deployed_by, '. Commit: ', commit_hash) AS description
FROM deployments
WHERE environment = 'production'
AND deployed_at >= DATE_TRUNC('day', NOW() - INTERVAL '90 days')
ORDER BY deployed_at DESC
This query pulls recent production deployments, enriches them with context, and orders them chronologically—perfect for an annotation layer.
Troubleshooting Common Annotation Issues
Annotations Not Appearing on Charts
The most common issue: timezone mismatches. Your annotation table’s timestamps might be in UTC, while your chart’s x-axis is in a different timezone. Superset should handle this automatically, but it’s worth verifying.
Also check that your chart’s time column is actually a datetime type, not a string. Superset can’t align annotations to string-based x-axes.
If you’re experiencing issues with annotations on time-series line charts, refer to the Apache Superset GitHub repository for known bugs and workarounds.
Performance Degradation
If your dashboard becomes slow after adding annotations, you likely have a data source issue. Annotation queries that scan millions of rows will slow down chart rendering.
Solutions:
- Add indexes: Index the time column in your annotation table for faster queries.
- Partition tables: If your annotation table is large, partition it by date so queries only scan recent data.
- Aggregate: Pre-aggregate events (e.g., one row per deployment, not per log line) before using as an annotation source.
Stale Annotations
If your annotation data is updated infrequently (e.g., daily), your charts will show stale events. For real-time or near-real-time annotations:
- Use streaming: Set up a streaming pipeline (e.g., Kafka → Superset) to push events as they occur.
- Increase refresh frequency: Configure your Superset dataset to refresh more often (e.g., every 5 minutes instead of hourly).
- Use webhooks: For critical events (incidents, major deployments), trigger immediate updates via webhooks.
Integrating Annotations with Your Analytics Stack
Superset Annotations in Production Environments
At D23, we work with engineering and data teams to operationalize annotations across their entire analytics infrastructure. This means:
- Automated pipelines: Events flow automatically from your operational systems (CI/CD, incident management, product analytics) into your data warehouse and then into Superset.
- Real-time dashboards: Annotations update in real time as events occur, so your team always has current context.
- Embedded analytics: If you’re using embedded analytics to surface BI into your product, annotations help end users understand metric movements without context-switching to Slack or email.
Using Annotations with Embedded BI
If you’re embedding Superset dashboards into your product (e.g., showing customers their usage metrics, or showing your operations team system health), annotations become a critical feature for reducing support burden.
Instead of customers asking “Why did my usage spike yesterday?” you can annotate the chart with “Scheduled backup job ran from 2-3 AM.” This self-serves the answer and improves customer trust in your metrics.
Annotations and Data Governance
Annotations are metadata that should be governed like any other data asset. Consider:
- Who can create annotations: Should all users be able to add events, or only data teams?
- Audit trails: Who created each annotation, when, and why?
- Validation: Should annotations be reviewed before appearing on dashboards?
For teams with strict compliance requirements, implementing annotation governance ensures that dashboards remain trustworthy sources of truth.
Annotation Best Practices
Keep Annotations Meaningful
Not every event deserves an annotation. A minor bug fix deployed at 2 AM probably doesn’t need to be marked on your revenue chart. But a major feature launch, a critical incident, or a marketing campaign absolutely does.
Ask: “If I’m looking at this metric in six months, will this annotation help me understand what happened?” If the answer is no, don’t add it.
Use Consistent Naming Conventions
Annotation titles should be consistent and descriptive. Instead of:
- “Deploy”
- “v2.3”
- “Fixed bug”
Use:
- “Deployed pricing-service v2.3.1”
- “Fixed payment processing bug (Issue #4521)”
- “Marketing campaign: Black Friday email blast”
This makes dashboards self-documenting and reduces the need to hover over annotations for context.
Color-Code by Type
If you’re using multiple annotation layers, assign consistent colors:
- Blue for deployments
- Red for incidents
- Green for experiments or feature launches
- Yellow for maintenance or external events
This visual language helps viewers instantly understand what each annotation represents.
Document Your Annotation Sources
Create a data dictionary or wiki page documenting:
- Where each annotation layer sources its data
- How frequently it updates
- Who owns the data pipeline
- What events are included or excluded
This prevents confusion and makes it easier for new team members to understand the dashboards.
Annotations at Scale: Enterprise Considerations
For large organizations with hundreds of dashboards and thousands of events, annotation management becomes more complex.
Centralized Annotation Management
Instead of each team managing their own annotation tables, consider a centralized event registry. This might be a single “events” table in your data warehouse with columns for:
event_id: Unique identifierevent_type: Deployment, incident, campaign, etc.event_source: Which system generated the eventtimestamp: When it occurredservice_or_team: What part of your business it affectedmetadata: JSON blob with additional context
Teams query this registry to create annotation layers, ensuring consistency and reducing duplication.
Annotation Discovery and Reusability
As you accumulate annotation layers, make them discoverable. In Superset, you can:
- Name layers clearly: Use prefixes like “[Deployments]”, “[Incidents]”, “[Campaigns]” so they’re easy to find.
- Document in chart descriptions: When adding an annotation layer to a chart, document it in the chart’s description.
- Create templates: Build a few standard dashboards with pre-configured annotation layers that other teams can copy and customize.
Comparing Annotation Approaches: Superset vs. Competitors
While other BI platforms offer annotations, Superset’s approach is distinctive:
Superset’s strengths:
- Flexible data sources: Annotations can come from any table, query, or sheet—not just a proprietary event store.
- Open-source: You own the code and can customize annotation behavior.
- API-first: Annotations can be managed programmatically via Superset’s REST API.
- Cost-effective: No per-annotation licensing or seat charges.
Trade-offs:
- Setup required: You need to build your own event pipelines; Superset doesn’t have built-in integrations with every CI/CD platform.
- Maintenance: You’re responsible for keeping annotation data fresh and accurate.
For teams evaluating managed Superset platforms, annotation management is a key consideration. A managed provider should handle the operational burden of keeping annotation pipelines running, ensuring data freshness, and providing expert guidance on annotation architecture.
Building Your Annotation Strategy
Starting with annotations doesn’t require a massive project. Here’s a pragmatic roadmap:
Phase 1: Single Event Type (Week 1-2)
Pick one event type that would provide immediate value. For most engineering teams, this is deployments.
- Identify your deployment source (CI/CD logs, deployment service API, Git webhooks).
- Create a simple
deploymentstable with minimal columns:timestamp,service,version. - Build a single annotation layer and add it to your most-viewed dashboard.
- Measure: Are people finding this useful? Are they asking for more events?
Phase 2: Multiple Event Types (Week 3-4)
Once deployments are working, add incidents or campaigns.
- Reuse the pattern from Phase 1.
- Create separate annotation layers for each event type.
- Start experimenting with colors and naming conventions.
- Gather feedback from dashboard users.
Phase 3: Automation and Scale (Month 2+)
Once you have 3-4 annotation layers working reliably:
- Automate event ingestion: Set up scheduled jobs or webhooks to populate your annotation tables.
- Implement governance: Document annotation sources, establish naming conventions, define who can create annotations.
- Expand to other dashboards: Identify high-impact dashboards (revenue, system health, customer metrics) and add relevant annotations.
- Train your team: Show data and engineering teams how to use annotations in their daily work.
Conclusion: Annotations as a Data Culture Tool
Annotations are more than a visualization feature—they’re a tool for building a data-driven culture. When your dashboards are annotated with context, they become conversation starters rather than conversation enders. Instead of “Why did this metric move?” you have “What did we learn from this event?”
For data and engineering leaders, annotations solve a real problem: the gap between operational events and analytical visibility. They compress investigation time, reduce context-switching, and make dashboards more actionable.
Implementing annotations requires some upfront work—building event pipelines, designing schemas, configuring Superset. But the ROI is substantial: faster incident response, better product decisions, and dashboards that tell stories instead of raising questions.
If you’re running Apache Superset and haven’t yet implemented annotations, start this week. Pick one event type, build one annotation layer, and add it to your most-used dashboard. You’ll immediately see the value.
For teams looking to operationalize this at scale—building reliable annotation pipelines, integrating with your entire analytics stack, and embedding annotations into product-facing dashboards—D23’s managed Superset platform handles the operational complexity so your team can focus on insights. We manage the infrastructure, keep your annotation data fresh, and provide expert guidance on annotation architecture for production analytics.