---
title: Stack Activity
description: Per-stack event log showing deploys, restarts, config changes, and alerts, each attributed to the user or system process that triggered them.
---

The **Activity** tab in the right-hand **Anatomy** panel gives you a timestamped record of everything that happened to the selected stack: deploys, restarts, stops, starts, take-downs, image updates, drift events, and health gate outcomes. Every entry is attributed to the user or background process that triggered it, so you always have full operational context at a glance. The **files** and **Edit compose** buttons on the same header strip belong to the panel as a whole and stay available regardless of which tab is active.

<Frame>
  <img src="/images/stack-activity/activity-tab-populated.png" alt="Activity tab with the ACTIVITY tab selected in the header strip showing ANATOMY, ACTIVITY, DOSSIER, DRIFT, ENVIRONMENT, COMPOSE LABELS, NETWORKING, DOCTOR, STORAGE tabs. Under a YESTERDAY header, three events appear: 'plex updated by admin' with an up-arrow icon 17h ago, 'plex update started by admin' with an up-arrow icon 17h ago, and '[Node: Local] Stack &quot;plex&quot; has image updates available.' via Image Update 1d ago." />
</Frame>

## What you'll see

Each entry in the activity list contains four pieces of information:

| Field | Description |
|-------|-------------|
| **Icon** | Category of the event (deploy, restart, stop, start, take down, image update, drift, and others) |
| **Message** | What happened, for example `plex deployed`. Sensitive values such as tokens, secrets, basic-auth credentials, and bearer tokens are redacted before storage |
| **Attribution** | `by <username>` for user-initiated actions; `via <Subsystem>` for events triggered by background processes such as Auto-Heal or the Scheduler |
| **Time** | Relative time since the event: `just now`, `5m ago`, `2h ago`, `3d ago` |

If a [notification mute rule](/features/alerts-notifications#mute-rules) blocks delivery of a matching alert, the entry still appears here with a **Suppressed** badge next to the message. Hovering the badge shows which rule matched. Suppression only affects delivery to the bell and external channels; the activity row itself is never suppressed.

## Event categories

Eleven categories have a dedicated icon. Any other notification scoped to a stack (deploy failures, scan findings, monitor alerts) also flows into the timeline and renders with a generic activity icon. Automatic creation of missing external networks during deploy writes a history-only activity row (`network_auto_created`) on the stack timeline; it does not appear in the notification bell.

| Category | Example message |
|----------|-----------------|
| Deploy succeeded | `plex deployed` |
| Stack restarted | `dozzle restarted` |
| Stack stopped | `radarr stopped` |
| Stack taken down | `radarr taken down` (or `radarr taken down (volumes removed)` when the take-down included volume removal) |
| Stack started | `radarr started` |
| Image update applied | `Auto-update: stack "dozzle" updated with new images` |
| Drift detected | `Drift detected on sonarr: 2 findings` |
| Drift resolved | `Drift resolved on tautulli: 1 finding cleared` |
| Update started | `tautulli update started` |
| Health gate passed | `plex: health gate passed` |
| Health gate failed | `plex: health gate failed` |

## Day grouping

Events are grouped by day under three headers: **Today**, **Yesterday**, and **Earlier**. Within each group, events appear most-recent first. The grouping recomputes every minute so a panel left open past midnight automatically rolls the **Today** bucket into **Yesterday**.

## Live updates

New events stream in over the same WebSocket that powers the notification bell. The list updates without a page refresh while the tab is open. Duplicate events are deduplicated by ID, and the timeline is sorted by `(timestamp, id)` so events emitted within the same millisecond stay in a stable order.

If the WebSocket connection drops, a banner appears at the top of the timeline:

> Live updates offline; reconnecting…

New events are paused until the connection re-establishes. Existing entries remain visible. Once the banner clears, new events resume automatically without any action on your part.

## Pagination

The tab loads the 50 most recent events on open. If a stack has more recorded events, a **Load more** button appears at the bottom of the list. Each click fetches the next 50 older events. The button disappears once the timeline reaches the end of the stored history.

The underlying API endpoint, `GET /api/stacks/{stackName}/activity`, accepts an optional `before` (timestamp) and `beforeId` (row id) pair for cursor-based pagination. Both parameters must be sent together; sending `beforeId` without `before` is rejected.

## Empty state vs unavailable

Two states can make the tab look empty, and they mean different things:

- **No activity recorded yet** appears when the stack genuinely has no recorded events. This is normal for stacks that have not had any lifecycle actions since Sencho began tracking activity.
- **Activity unavailable** appears when the request to fetch events fails (for example, the node became unreachable mid-load). A **Retry** button is shown next to this message.

<Frame>
  <img src="/images/stack-activity/activity-tab-empty.png" alt="Activity tab showing a small activity icon and the message 'No activity recorded yet' centered in the panel, with no events listed." />
</Frame>

## Who triggered an event

Sencho attributes every recorded event to the actor that performed it:

- **User-initiated actions** (deploy, restart, stop, start, take down, image update triggered from a button or the API): the actor is the authenticated username, shown as `by <username>`.
- **Background subsystems**: the actor is the subsystem name, shown as `via <Subsystem>`.

| Background subsystem | Displayed as |
|----------------------|--------------|
| Generic system event | `via System` |
| Auto-Heal | `via Auto-Heal` |
| Scheduler | `via Scheduler` |
| Image Update | `via Image Update` |
| Docker event monitor | `via Docker` |
| Blueprint reconciler | `via Blueprint` |
| Host Monitor | `via Monitor` |
| Policy enforcement | `via Policy` |

An Auto-Heal restart and a manual restart produce separate entries in the timeline because their actors differ, even when the event message is otherwise identical.

## Retention

Activity is stored in a per-instance SQLite table. Two limits apply, whichever is reached first:

- **Time-based:** events older than the configured retention window (30 days by default) are removed during the next periodic cleanup.
- **Per-stack cap:** the most recent 500 events per (node, stack) are kept. Older events for that stack are pruned on the next cleanup run.

Events without an associated stack (system-level notifications) are kept up to 1,000 per node before the oldest are removed.

Cleanup runs on the same schedule as container-metrics cleanup, so retention applies even on long-running instances.

## Accessing the Activity tab

1. Click any stack in the left sidebar to open it.
2. Select the **Activity** tab in the Anatomy panel header.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The Activity tab shows 'No activity recorded yet'">
    This is normal for stacks that have not had any lifecycle actions (deploy, restart, stop, update) since Sencho started tracking activity. The tab populates the first time a lifecycle event is recorded. Events that occurred before Sencho was installed are not backfilled.
  </Accordion>
  <Accordion title="The Activity tab shows 'Activity unavailable'">
    The request to fetch activity failed, usually because the node is unreachable or the backend returned a server error. Click **Retry** to re-fire the request without reloading the page. If the node has been removed or its credentials have changed, go to **Settings → Nodes** to verify the connection.
  </Accordion>
  <Accordion title="An event I triggered is not appearing in the timeline">
    Live events arrive over WebSocket. If the "Live updates offline; reconnecting…" banner is visible, new events are paused until the connection recovers. Scroll down to check whether the event is already present below the visible viewport, or wait for the banner to clear and the event will appear automatically. If the event still does not show up, check the notification bell for error-level alerts that may indicate the action itself did not complete.
  </Accordion>
  <Accordion title="The same restart shows as both 'by &lt;username&gt;' and 'via Auto-Heal'">
    These are two distinct events. The first is a manual restart; the second is Auto-Heal restarting the container after a separate unhealthy-duration breach. Each event is its own entry with its own actor. Two rows here are correct behavior, not a duplicate.
  </Accordion>
  <Accordion title="Operational events don't appear in the notification bell dropdown">
    The notification bell surfaces system alerts and error-level events. User-initiated operational events (start, stop, restart, take down, deploy, update) appear exclusively in the per-stack Activity tab, keeping the global tray focused on conditions that need your attention.
  </Accordion>
</AccordionGroup>
