---
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, starts, stops, and image updates. Each entry shows who triggered the event so you always have operational context. The `files` and `edit` actions on the same 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="Stack Activity tab showing events grouped by Today, Yesterday, and Earlier with restart, auto-update, and image-update entries" />
</Frame>

## What you'll see

Each entry in the activity list contains:

| Field | Description |
|-------|-------------|
| **Icon** | Category of the event (deploy, restart, stop, start, image update applied) |
| **Message** | What happened (for example, `dozzle restarted`). Sensitive values such as tokens, secrets, basic-auth credentials, and bearer tokens are redacted before storage |
| **Attributed to** | `by <username>` for user-initiated actions; `via <Subsystem>` for events generated by background processes (Auto-Heal, Scheduler, Image Update, Docker, Blueprint, Monitor, Policy) |
| **Time** | Relative time since the event: `just now`, `5m ago`, `2h ago`, `3d ago` |

## Event categories

The five operational categories below have a dedicated icon. Other notification categories that scope to a stack (deploy failures, available image updates, auto-heal triggers, monitor alerts, scan findings) also flow into the timeline and render with a generic activity icon.

| Category | Icon | Example message |
|----------|------|-----------------|
| Deploy succeeded | rocket | `plex deployed` |
| Stack restarted | refresh | `dozzle restarted` |
| Stack stopped | stop | `radarr stopped` |
| Stack started | play | `radarr started` |
| Image update applied | up arrow | `Auto-update: stack "dozzle" updated with new images` |

## Day grouping

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

## Live updates

New events stream in over the same WebSocket that powers the notification bell, so 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.

## Pagination

The tab loads the most recent 50 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 stops appearing 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. The two parameters must move together; sending `beforeId` without `before` is rejected.

## Empty state vs unavailable

Two empty-looking states exist and they mean different things:

- **No activity recorded yet** appears when the stack genuinely has no recorded events.
- **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 it.

<Frame>
  <img src="/images/stack-activity/activity-tab-empty.png" alt="Stack Activity tab in its empty state with a heartbeat icon and the message 'No activity recorded yet'" />
</Frame>

## Who triggered an event

Sencho attributes every recorded event to whichever actor performed it:

- **User-initiated actions** (deploy, restart, stop, start, image update from a button click or the API): the actor is the authenticated username, shown as `by <username>`.
- **Background subsystems** (Auto-Heal, Scheduler, Image Update, Docker event monitoring, Blueprint reconciler, Host Monitor, Policy enforcement): the actor is the subsystem name, shown as `via Auto-Heal`, `via Scheduler`, and so on.

An autoheal restart and a manual restart are visually distinct in the timeline because the actor differs.

## Retention

Activity is stored in a per-instance SQLite table. Two limits apply, whichever comes 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 retained. Older events for that stack are removed during the next periodic cleanup.

Events without an associated stack (system-level notifications) are kept up to 1000 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. Switch to the **Activity** tab in the Anatomy panel header.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The Activity tab shows 'No activity recorded yet'">
    The activity log is populated by operations performed through Sencho on this stack: deploys, restarts, starts, stops, and image updates. Trigger one of those actions and the entry appears within a few seconds.
  </Accordion>
  <Accordion title="The Activity tab shows 'Activity unavailable'">
    The request to fetch activity failed, usually because the node is currently unreachable or the backend returned a server error. Click **Retry** to attempt the request again. If the node has been removed or its credentials are stale, the activity for that node is no longer accessible.
  </Accordion>
  <Accordion title="An event I expected to see is missing">
    Two reasons this can happen. First, the event may be older than the 30-day retention window. Second, if the stack has had more than 500 events recorded, the oldest are pruned automatically. To preserve a longer history, route the events to an external channel via **Notification Routes**.
  </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 your manual click; the second is Auto-Heal restarting the same container after a separate unhealthy-duration breach. Each event is its own row with its own actor.
  </Accordion>
  <Accordion title="Operational events don't appear in the bell notification dropdown">
    The notification dropdown surfaces system alerts and error-level events. User-initiated operational events (start, stop, restart, deploy, update) appear exclusively in the per-stack Activity tab, keeping the global tray focused on conditions that need your attention.
  </Accordion>
</AccordionGroup>
