Sessions

Release health tracking via session lifecycle updates and crash-free rate computation.

Statusstable
Version1.7.0(changelog)

Sessions allow Sentry to track the health of releases by monitoring when applications start, end, crash, or encounter errors. SDKs send session update events as session or sessions envelope items. Sentry uses this data to compute crash-free rates, error rates, and session durations per release.

Related specs:


SDKs operate in one of two session modes:

  • User-mode (application-mode) — A single session spans the full application run. Typical for mobile apps, desktop apps, CLI tools, and browser sessions. Session duration is meaningful.
  • Server-mode (request-mode) — Each HTTP request or RPC call is a separate session. High volume, short-lived. Duration is typically not useful. Sessions SHOULD be pre-aggregated before sending.

A session progresses through these states:

Copied
[init] → ok → exited | unhandled | crashed | abnormal
  • ok — session is in progress and healthy
  • exited — session terminated normally (duration is tracked)
  • unhandled — session terminated with an unhandled error
  • crashed — session terminated in a crash (process terminated)
  • abnormal — session fate is unknown (e.g., power loss, force kill)

Sentry's session system uses hourly buckets of pre-materialized data. Session updates are immediately materialized into the correct bucket on arrival. This means the protocol is additive only — the client MUST store the entire session state and send it with each update.


Stablespecified since 1.0.0

Sessions are entirely client-driven. The client determines when a session starts, ends, or transitions to an unhealthy state.

  • Sessions are updated through session change events that hold the entire session state. The most recent event holds the authoritative state.
  • The initial session event MUST have init set to true. This lets the server skip deduplication. Internally, seq is set to 0 when init is true.
  • Sessions can only be updated for 5 days. After that, a session without a second event is permanently marked as good.
  • A session does not have to be started in order to crash — just reporting a crash is sufficient.
Stablespecified since 1.0.0

SDKs MUST NOT change session attributes (did, started, or any attrs fields) in subsequent updates. Only status, duration, and errors MAY change. If a user is not known at session start, the session start SHOULD be delayed or the session restarted once the user is known.

Stablespecified since 1.0.0

Once a session reaches a terminal state, the SDK MUST NOT send further updates. Terminal states are: exited, crashed, abnormal, and (since 1.6.0) unhandled.

SDKs SHOULD distinguish between terminal states:

  • exited: The session ended cleanly. Only exited sessions have their duration averaged. A session MAY exit even if errors occurred.

  • unhandled (since 1.6.0): An unhandled error occurred but the process did not terminate. Use when:

    • An unhandled error occurred with a natural session end (e.g., end of HTTP request).
    • The application did not handle an error, but the language or framework prevented termination.
  • crashed: The application process terminated. Use when:

    • A complete crash occurred (crash to desktop, process termination).
    • A user feedback dialog is surfaced. After this, the SDK MUST start a new session.
  • abnormal: The session fate is unknown. SDKs SHOULD prefer exited or crashed when possible. Use when the application did not shut down correctly (e.g., power loss, kill -9, task manager). Abnormal session ends are normally recorded on application restart.

Stablespecified since 1.0.0

SDKs MUST maintain a running errors counter that is incremented when errors occur during the session. The counter MUST also be incremented when a session goes to crashed (the crash itself is always an error). Ingest forces errors to 1 if not set or 0.

A session that is ok with errors > 0 is considered "errored." All crashed and abnormal sessions are also considered errored but are subtracted from the final errored count.

(since 1.7.0) Only events from captureException, captureError, or captureEvent MUST increment the errors counter, and only when their level is error or higher. Events from captureMessage MUST NOT affect the session error count regardless of level.

MethodLevelIncrements errors
captureException / captureErrorfatalYes
captureException / captureErrorerrorYes
captureException / captureErrorwarningNo
captureEventfatalYes
captureEventerrorYes
captureEventwarningNo
captureMessagefatalNo
captureMessageerrorNo
captureMessagewarningNo
Stablespecified since 1.1.0

SDKs SHOULD default to the session mode most appropriate for the language ecosystem:

User-mode (application-mode):

  • Typically a single session from application start to quit.
  • (since 1.3.1) On mobile, sessions MAY end when the app is backgrounded for over 30 seconds.
  • Sessions span multiple hubs/threads.
  • Session duration is meaningful (typically minutes).

Server-mode (request-mode):

  • One session per HTTP request or RPC call.
  • High volume — sessions SHOULD be pre-aggregated.
  • Sessions are attached to a single hub/concurrency unit.
  • Timing information is typically not useful.

When using user-mode, a single session SHOULD start at application initialization and persist through the runtime. When using server-mode, no application-wide session SHOULD be started — sessions are started/ended per request by integrations.

(since 1.3.0) If an SDK can detect that an application is better served by session aggregates, it MUST NOT report an application-wide session. The application-wide session may still be created during initialization but MUST be aborted and never sent to Sentry.

Stablespecified since 1.2.0

Server-mode SDKs SHOULD pre-aggregate closed sessions before sending to Sentry. When a session closes and has not been sent upstream (its init flag would be true), it is eligible for aggregation:

  1. Round the started timestamp down to the minute.
  2. Aggregate into the bucket identified by the rounded timestamp and did.
  3. Increment the count for the session's terminal status. Use errored for sessions with exited status and non-zero errors count.

(since 1.3.0) SDKs SHOULD use a periodic session flusher (every 60 seconds) that sends the aggregated sessions envelope item. When a client is closed or flushed, the session flusher MUST also be flushed before the transport is closed.

Stablespecified since 1.4.0

When events are dropped by filtering mechanisms (sample rate, rate limiting, beforeSend, event processors, or ignored exception types), the session update behavior depends on the drop reason:

  • Events dropped due to sampling or rate limiting SHOULD still update the session — the event was dropped to save quota but represents something the developer cares about.
  • Events dropped for other reasons (beforeSend, event processors, ignored types) SHOULD NOT update the session — the developer chose to ignore them.

(since 1.4.1) Rate limited events SHOULD update the session despite being dropped.

If the event has been dropped but the session was updated, the session update SHOULD be sent to the server without the event in case the session changed from healthy to errored or from any state to crashed (for user-attended sessions).

Filter order (Python SDK as reference):

  1. Check for ignored exception types (ignore_errors)
  2. Apply scoped event processors
  3. Apply global event processors
  4. Apply beforeSend
  5. Update the session if the event made it this far
  6. Apply sampling rate
Stablespecified since 1.1.0

SDKs SHOULD automatically update the current session whenever data is captured (at the same point where apply_to_scope is called) to increment the errors count or update the session based on the distinct ID.

SDKs SHOULD aim to minimize the number of envelopes sent upstream.

Server-mode SDKs SHOULD use the periodic session flusher with pre-aggregation. User-mode SDKs MAY send session updates alongside captured events in the same envelope. The final session update MAY be batched.

The init flag MUST be set correctly for the first transmission of the session. Session metadata MUST be immutable after the initial transmission.

SDKs SHOULD send session updates in the same envelope as crash events when transitioning to crashed. This ensures both arrive together over unreliable networks.


Stablespecified since 1.0.0

A session update is sent as a session envelope item containing a JSON object. Multiple session envelope items MAY appear in a single envelope. Ingestion may limit the maximum number of items per envelope.

FieldTypeRequiredSinceDescription
sidStringOPTIONAL1.0.0Session ID (UUID, client-generated). MAY be skipped if initial state is exited.
didStringOPTIONAL1.0.0Distinct ID (device or user ID). Automatically hashed before storage.
seqNumberOPTIONAL1.0.0Logical clock. Defaults to current UNIX timestamp in milliseconds. Forced to 0 when init is true.
timestampStringOPTIONAL1.0.0ISO DateTime of when the update occurred. Defaults to current UTC time. Called received in the data model.
startedStringREQUIRED1.0.0ISO DateTime of when the session started.
initBooleanOPTIONAL1.0.0true for the first event of the session. Default: false.
durationNumberOPTIONAL1.0.0Session duration in seconds (float). Inactive time MAY be subtracted.
statusStringOPTIONAL1.0.0Session status. Default: ok. One of: ok, exited, crashed, abnormal, or (since 1.6.0) unhandled.
errorsNumberOPTIONAL1.0.0Running error count. Default: 0. MUST be incremented on crash.
abnormal_mechanismStringOPTIONAL1.5.0Mechanism that caused abnormal status (e.g., ANR detection). Default: none.
attrsObjectREQUIRED1.0.0Session attributes. See Session Attributes.

FieldTypeRequiredSinceDescription
releaseStringREQUIRED1.0.0Release version (suggested format: my-project-name@1.0.0).
environmentStringOPTIONAL1.0.0Environment name.
ip_addressStringOPTIONAL1.0.0User IP address for filtering. Not persisted. Auto-filled if not set.
user_agentStringOPTIONAL1.0.0User agent string for filtering. Not persisted.
Stablespecified since 1.2.0

For server-mode sessions, SDKs SHOULD send aggregated session counts as a sessions envelope item. Multiple sessions envelope items MAY appear in a single envelope. Ingestion may limit the maximum number of items per envelope.

FieldTypeRequiredSinceDescription
aggregatesArrayREQUIRED1.2.0Array of aggregate groups. See below.
attrsObjectREQUIRED1.2.0Session attributes (same as individual session attrs).

FieldTypeRequiredSinceDescription
startedStringREQUIRED1.2.0Timestamp rounded down to the minute. ISO DateTime.
didStringOPTIONAL1.2.0Distinct user ID for this group.
exitedNumberOPTIONAL1.2.0Sessions with exited status and zero errors.
abnormalNumberOPTIONAL1.2.0Sessions with abnormal status.
unhandledNumberOPTIONAL1.6.0Sessions with unhandled status.
crashedNumberOPTIONAL1.2.0Sessions with crashed status.
erroredNumberOPTIONAL1.2.0Sessions with exited status and non-zero errors count.

Stablespecified since 1.1.0

SDKs MUST expose a function to start a session:

Copied
startSession() -> void

Stores a session on the current scope and starts tracking it. This implicitly ends any existing session.

(since 1.3.0) Sessions SHOULD be enabled by default for the global hub/client initialized by Sentry.init(), and disabled by default for manually created clients.

Naming SHOULD follow the SDK's language conventions:

  • Sentry.startSession() (JavaScript)
  • Hub.start_session() (Python)
Stablespecified since 1.1.0

SDKs MUST expose a function to end a session:

Copied
endSession() -> void

Ends the session, setting an appropriate status and duration, and enqueues it for sending to Sentry. SDKs MUST NOT send further updates for an ended session.

Naming SHOULD follow the SDK's language conventions:

  • Sentry.endSession() (JavaScript)
  • Hub.end_session() (Python)
Stablespecified since 1.1.0

SDKs SHOULD accept an autoSessionTracking configuration option (boolean, default varies by SDK).

When enabled, the SDK automatically starts and ends sessions based on the session mode. SDKs MAY also expose startAutoSessionTracking() / stopAutoSessionTracking() for runtime control.

Naming SHOULD follow the SDK's language conventions:

  • autoSessionTracking (JavaScript)
  • auto_session_tracking (Python)

Copied
{
  "sid": "7c7b6585-f901-4351-bf8d-02711b721929",
  "did": "optional distinct user id",
  "init": true,
  "started": "2020-02-07T14:16:00Z",
  "duration": 60,
  "status": "exited",
  "attrs": {
    "release": "my-project-name@1.0.0",
    "environment": "production"
  }
}

Copied
{
  "aggregates": [
    {
      "started": "2020-02-07T14:16:00Z",
      "exited": 123
    },
    {
      "started": "2020-02-07T14:16:00Z",
      "did": "optional distinct user id",
      "exited": 12,
      "errored": 3
    }
  ],
  "attrs": {
    "release": "my-project-name@1.0.0",
    "environment": "development"
  }
}

Copied
{}
{"type":"session"}
{"sid":"7c7b6585-f901-4351-bf8d-02711b721929","init":true,"started":"2020-02-07T14:16:00Z","status":"ok","attrs":{"release":"my-project-name@1.0.0"}}

Copied
{}
{"type":"sessions"}
{"aggregates":[{"started":"2020-02-07T14:16:00Z","exited":123}],"attrs":{"release":"my-project-name@1.0.0"}}

VersionDateSummary
1.7.02025-10-16Added error level impact rules for session error counting
1.6.02025-09-30Added unhandled session status
1.5.12025-07-16Clarified session envelope wording
1.5.02023-05-08Added abnormal_mechanism field to session payload
1.4.12022-11-14Clarified rate limited events should update sessions
1.4.02022-04-26Added session update filtering requirements for dropped events
1.3.12021-06-02Added mobile session background timeout note
1.3.02021-05-17Added SDK implementation guidelines (individual sessions, session aggregates)
1.2.12021-01-13Updated release format to match suggested pattern
1.2.02020-12-02Added session aggregates payload
1.1.12020-09-02Clarified session modes and improved documentation
1.1.02020-08-28Added SDK considerations (session modes, exposed API, update recommendations)
1.0.02020-05-25Initial spec — session update payload, basic operation, server model
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").