Usage, Metering & Capabilities
LogTide measures resource consumption per organization and project, and can gate features and enforce limits and quotas through a typed capability system. Both are the groundwork for plan tiers in a hosted distribution — and both are OSS-permissive by default, so self-hosted behavior is unchanged until an operator sets a cap.
Self-hosted defaults
Every feature gate ships enabled and every limit/quota ships unlimited. Nothing here restricts a self-hosted instance unless you deliberately configure an organization cap.
Overview
Metering
Records what each organization consumes — ingested bytes/events, spans, and estimated storage.
Capabilities
A typed registry of feature gates, static limits, and usage quotas, with per-org overrides.
Audit log
A structured record of security-relevant actions, with typed actions, actors, outcomes and retention.
Usage Metering
Metering records consumption events into a dedicated TimescaleDB hypertable through a non-blocking, loss-tolerant in-process recorder. Calls are buffered and batch-inserted on a size threshold, a flush interval, and on graceful shutdown — under back-pressure the recorder drops rather than blocking the request path, because metering is measurement, not audit.
Recording sites:
logs.ingested.bytesandlogs.ingested.events— recorded fire-and-forget after each log ingest (OTLP ingestion is metered too).spans.ingested— recorded after span ingestion, activating the tracing quota.storage.snapshot— a daily per-(organization, project) estimate of stored bytes, computed as the logical bytes ingested within the org's retention window. Engine-agnostic by design: it never scans the reservoir and ignores compression and manual deletions.
The dashboard surfaces all of this under a Usage section. Read APIs:
GET /api/v1/usage # grouped totals and a daily series
GET /api/v1/usage/breakdown # by type, project, service, and log level
GET /api/v1/usage/storage # current estimate + daily storage trend
GET /api/v1/usage/capabilities # live usage vs each configured capability limit Storage estimate caveat
Organizations with pre-metering data under-estimate storage until a full
retention_days window of metering history accumulates. This is self-healing
(typically within 90 days).
Capabilities & Limits
A typed capability registry is the single source of truth for the platform's gates, limits and quotas, across three kinds:
| Kind | Examples | Enforced by |
|---|---|---|
| Boolean gates | auth.sso, detection.advanced, audit.enabled, isolation.dedicated | assertCapability → 403 |
| Static limits | alerts.max_rules, notifications.max_channels, apikeys.max, sigma.max_active_rules, dashboards.max_custom, audit.retention_days | assertWithinLimit → 403 |
| Usage quotas | ingestion.max_bytes_monthly, ingestion.max_events_monthly, storage.max_bytes, tracing.max_spans_monthly | assertWithinUsageQuota → 429 |
Per-org overrides live in an organization_entitlements key-value table. A
cache-backed resolver merges those rows over the registry defaults, fails open
on database errors, and is swappable — a hosted distribution can source entitlements from
subscription state without patching core. Overrides are edited from the
Entitlements card on the admin organization page (boolean switches and numeric
caps; an empty cap means unlimited). Members can read the merged set for UI gating:
GET /api/v1/capabilities # merged set for the current org (UI gating)
GET /api/v1/admin/organizations/:id/entitlements # admin: read per-org overrides
PUT /api/v1/admin/organizations/:id/entitlements # admin: set per-org overrides Quota Enforcement
Usage quotas join metering to enforcement through a periodic in-process evaluator. It reads month-to-date totals for organizations that have at least one non-null quota cap and maintains an in-memory over-quota flag — so the ingestion hot path never touches the database for a quota check. Enforcement short-circuits on a null (unlimited) limit, which doubles as the defense when an admin lifts a cap.
When a limit or quota is hit, the global error handler returns a machine-readable
code on the response (for example
capability.alerts.max_rules.limit_reached), so clients and the dashboard can react
precisely rather than parsing a message string.
Plan limits on the usage page
The usage page shows current consumption against each configured limit as a color-coded progress bar — green below 80%, amber 80–99%, red at or above 100%. A null limit renders as “Unlimited”, so OSS defaults read correctly.
Audit Log
The audit log is a structured security primitive backed by a canonical action registry — 70
typed actions across families like org.*, apikey.*,
rule.*, auth.* and data.*. Because actions are a typed
union, typos fail to compile, and the audit category is derived from the registry rather than
hand-passed at each callsite.
Records capture the organization, the actor (user, API key, or system), the outcome
(success / failure), and the request IP and user agent — read
automatically from the request context, so callsites only state the action and target. Because
actors now come from the request context, API-key access to query endpoints is audited too, and
failed local logins are recorded as auth.login_failed with a failure outcome.
The audit page in settings exposes actor-type, outcome and time-range filters; the query API and
CSV export carry the same columns. Retention is per organization: audit_retention_days
(1–3650 days, or NULL to keep forever — the default) is editable from the admin organization page
and enforced by the daily retention job.
Configuration
| Variable | Description |
|---|---|
METERING_ENABLED | Toggle the usage recorder. |
METERING_FLUSH_INTERVAL_MS | How often the buffered recorder flushes to the database. |
METERING_FLUSH_MAX_BUFFER | Buffer size that triggers an early flush. |
QUOTA_EVALUATOR_ENABLED | Toggle the periodic quota evaluator. |
QUOTA_EVALUATOR_INTERVAL_MS | How often month-to-date totals are recomputed (default 60s). |
STORAGE_SNAPSHOT_ENABLED | Toggle the daily storage snapshot job. |
STORAGE_SNAPSHOT_INTERVAL_MS | Storage snapshot cadence (default 24h). |
To act on usage or enforce custom policy on the hot path, see the
Lifecycle Hooks guide — the afterIngest phase
reports per-batch accepted/rejected counts, and beforeIngest can reject a batch
outright.