LogTide
v1.4.0
Released
Feature

1.4.0: Ready to Host LogTide for Others, Opt-In by Design

A feature release that makes LogTide ready to run as a hosted multi-tenant service, the same groundwork that powers LogTide Cloud. A combined byte quota, email verification, terms acceptance, quota grace and per-user caps are all opt-in: self-hosted installs behave exactly as before.

  • Combined monthly byte quota across logs, traces and metrics: logs, spans and metrics are now all metered in bytes
  • Quota grace period with immediate in-app and email notices when a quota is reached or blocked
  • Optional email verification and Terms/Privacy acceptance at registration
  • Per-user caps on owned organizations and monthly creations, plus a projects.max limit
  • Set instance-wide limits at boot with CAPABILITY_DEFAULTS_JSON
  • Fixed: entitlement limits of 2 GiB and above no longer fail with an out-of-range error

A feature release that makes LogTide ready to be run as a hosted, multi-tenant service. It is the groundwork behind LogTide Cloud, and it ships in the open so anyone who hosts LogTide for other people gets the same building blocks. Everything new is opt-in and inert unless you set the matching environment variable, so if you run LogTide for yourself or your team nothing changes: same defaults, same behavior, same API. The full list of variables, with defaults and validation rules, is in the new hosting guide.

Added

  • Combined monthly byte quota: logs, spans and metrics are now all metered in bytes, so one month-to-date quota can cover all three signals together. A secondary datapoint limit, metrics.max_datapoints_monthly, caps how many metric datapoints an organization can ingest. It is unlimited by default. Once an organization goes over the limit (plus any grace margin), the OTLP metrics endpoint answers 429 while logs and traces keep flowing. It shows up on the Usage page as “Metric datapoints (this month)”
  • Metric datapoint metering: accepted OTLP metric datapoints are now measured and recorded in usage data, like spans already were. Datapoints that were not stored are never counted
  • Quota grace and instant notifications: a new quota.grace_percent setting lets a quota overshoot by a margin before it blocks. Between the limit and that ceiling the quota is “In grace”, past it “Blocked”, and the Usage page shows both as badges. The first time a quota enters grace or becomes blocked in a month, owners and admins get an in-app notification and an email, once per organization even when you run several backend replicas. Raising a limit mid-month re-arms the notice at the new ceiling
  • Optional email verification: set REQUIRE_EMAIL_VERIFICATION=true and newly registered users must confirm their address before creating projects, API keys or receivers. Registration still logs them in right away, and the verification email is sent in the background so signing up never waits on your mail server. Links are single use and expire after 24 hours, resending is rate limited, and the app shows a “Verify your email” banner with a resend button. Existing users are never locked out, and SSO users are treated as verified when the identity provider says so
  • Terms and Privacy acceptance: set LOGTIDE_TERMS_URL, LOGTIDE_PRIVACY_URL and LOGTIDE_TERMS_VERSION and registration requires accepting both. The accepted version and time are stored on the user. When you bump the version, everyone sees a blocking modal and must accept again before creating organizations, projects or API keys. Ingestion with existing API keys is never blocked
  • Hourly registration limit: REGISTRATION_RATE_LIMIT_PER_HOUR caps sign-ups per client IP over a one-hour window, on top of the existing auth rate limit
  • Organization caps per user: MAX_ORGANIZATIONS_PER_USER limits how many organizations one user can own, and MAX_ORGANIZATION_CREATIONS_PER_USER_PER_MONTH limits how many they can create per month, so deleting an organization and starting a fresh one can no longer reset its monthly quotas. Parallel requests can no longer slip past the cap
  • Projects limit: a new projects.max capability caps active projects per organization (soft-deleted ones do not count). It also applies when restoring a deleted project, and it appears as “Projects” on the Usage page
  • Instance-wide capability defaults: CAPABILITY_DEFAULTS_JSON sets the default value of any limit, gate or quota at boot. It is validated on startup, so a typo aborts with a clear error instead of silently doing nothing, and per-organization overrides still win
  • Upgrade link for hosted plans: setting LOGTIDE_UPGRADE_URL and LOGTIDE_UPGRADE_SIGNING_SECRET adds Upgrade and Manage billing buttons for owners and admins, which open your own billing portal with a short-lived signed token. Quota and capability denials tell clients that an upgrade is available. Unset, no button and no new fields appear
  • Admin service token: LOGTIDE_ADMIN_SERVICE_TOKEN lets an external service manage organization entitlements and retention through the admin API with a static bearer token, honored on those routes only and recorded in the audit log
  • Hosting guide: a new guide, Hosting LogTide for others, documents every variable above, the handoff token format with a reference verifier, and operator notes. The contributing guide also now spells out the architectural rules every pull request must respect, and documents the Contributor License Agreement

Changed

  • Default quotas now apply to every organization: when a finite quota default is set through CAPABILITY_DEFAULTS_JSON, quota checks cover all organizations, including ones that never had an override, so a default quota actually blocks. With no quota defaults set, behavior is identical to before
  • Docker Compose passes the new variables through: the bundled Compose files forward all hosting variables to both the backend and the worker, empty when unset, which keeps them inert

Fixed

  • Entitlement limits of 2 GiB and above: setting any byte quota from 2 GiB up, such as a 10 GiB monthly ingestion limit, failed with an “integer out of range” error and the admin API answered 400. Limits now support the full range
  • Credentials in rate-limit keys: with Redis configured, the global rate limiter stored every live API key and session token in plain text in Redis key names. Keys are now a hash of the credential, and counting per credential is unchanged
  • Docker image builds: the backend and frontend images installed an unpinned pnpm and could pick up a newer major that ignores the workspace dependency overrides. Both Dockerfiles now pin pnpm 10

Security

  • Dependency updates: fastify, nodemailer, js-yaml, undici, fast-uri, @fastify/busboy, devalue, shell-quote, vitest and several transitive packages were updated to clear every open Dependabot advisory, including one critical and several high severity issues. The full list of advisories is in the repository changelog