# Monitoring Tenant Usage and Daily Active Users in Logto: A Complete Technical Guide

> Monitor tenant usage and daily active users in Logto using sign-in event aggregation and the Dashboard API. Learn how Logto enforces limits and tracks key metrics in this technical guide.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-04

---

**Logto tracks tenant usage by aggregating sign-in events into an `aggregated_daily_active_users` table, exposing DAU/WAU/MAU metrics through a dedicated Dashboard API, and enforcing limits via a memoized quota library.**

In the **logto-io/logto** repository, monitoring tenant usage and daily active users is essential for multi-tenant quota enforcement and billing. The implementation spans database schema migrations, nightly aggregation jobs, and a read-only Dashboard API that exposes real-time metrics to administrators.

## Data Collection and Aggregation Architecture

Logto employs a two-tier storage strategy to balance write performance with read efficiency. Raw sign-in events populate the `daily_active_user` table, while a nightly aggregation job condenses these records into the `aggregated_daily_active_users` table for fast querying.

### The Aggregated Daily Active Users Table

The `aggregated_daily_active_users` table schema is defined in [`packages/schemas/tables/aggregated_daily_active_users.sql`](https://github.com/logto-io/logto/blob/main/packages/schemas/tables/aggregated_daily_active_users.sql). This table stores pre-computed counts per tenant and date, eliminating the need to scan millions of raw sign-in rows when generating dashboards.

The migration script at [`packages/schemas/alterations/1.35.0-1764580589-create-aggregated-daily-active-users-table.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/alterations/1.35.0-1764580589-create-aggregated-daily-active-users-table.ts) creates this table and establishes two critical indexes:

- **Tenant and date index**: Accelerates filters for specific time ranges.
- **Tenant, user, and date index**: Supports unique user counting within periods.

These indexes ensure that DAU/WAU/MAU calculations remain performant even as tenant data scales.

### Nightly Aggregation Process

A background job automatically aggregates raw `daily_active_user` records into the aggregated table. This denormalization strategy keeps the operational table small while maintaining historical accuracy for billing and analytics.

## Querying Daily Active Users

Logto exposes tenant usage metrics through a dedicated query module and REST API endpoint, allowing both the admin console and external integrations to consume standardized activity data.

### The Daily Active User Query Module

The file [`packages/core/src/queries/daily-active-user.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/queries/daily-active-user.ts) contains the database queries that compute **DAU** (Daily Active Users), **WAU** (Weekly Active Users), and **MAU** (Monthly Active Users). This module also retrieves a 30-day history of DAU values for trend analysis.

Internally, these queries leverage the indexes created by the migration script to return results in milliseconds, even when calculating rolling windows across large tenant datasets.

### Dashboard API Endpoint

The Dashboard API specification is defined in [`packages/core/src/routes/dashboard.openapi.json`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/dashboard.openapi.json). This OpenAPI-compliant endpoint exposes tenant usage data via a secure, read-only interface.

The endpoint returns the following metrics:
- Current DAU, WAU, and MAU counts
- A 30-day time series of DAU values

Administrators can consume this endpoint to build custom monitoring dashboards or integrate usage data into external analytics platforms.

## Enforcing Usage Quotas

Before any operation that could affect tenant limits, Logto checks current usage against configured quotas using a centralized library that prevents duplicate database queries.

### Quota Library Implementation

The [`packages/core/src/libraries/quota.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/quota.ts) file implements the **quota enforcement** logic. The library provides `getTenantUsageByKey()`, which retrieves current usage counts for specific metrics like `dailyActiveUser`.

To optimize performance, the quota library **memoizes** usage queries within the request lifecycle. This prevents redundant database hits when multiple operations check limits during a single transaction.

## Practical Implementation Examples

### Fetching Usage via the Dashboard API

Use this Node.js example to retrieve current tenant metrics from the Logto Core service:

```javascript
import fetch from 'node-fetch';

const tenantId = 'your-tenant-id';
const apiKey = 'your-api-key';
const baseUrl = 'http://localhost:3001/api';

async function getTenantUsage() {
  const response = await fetch(`${baseUrl}/dashboard/usage?tenantId=${tenantId}`, {
    headers: { 'Authorization': `Bearer ${apiKey}` },
  });

  if (!response.ok) {
    throw new Error(`Failed to fetch usage: ${response.status}`);
  }

  const data = await response.json();
  console.log('DAU:', data.dailyActiveUser);
  console.log('WAU:', data.weeklyActiveUser);
  console.log('MAU:', data.monthlyActiveUser);
  console.log('30-day DAU history:', data.dailyActiveUserInPast30Days);
}

getTenantUsage().catch(console.error);

```

### Running the Aggregation Job Manually

While Logto runs the aggregation automatically, you can trigger it manually for testing:

```bash
pnpm cli daily-aggregation run

```

### Checking Quotas Programmatically

Integrate quota checks into your custom logic using the quota library:

```typescript
import { getTenantUsageByKey } from '@logto/core/src/libraries/quota';

async function canCreateNewUser(tenantId: string) {
  const { dailyActiveUser } = await getTenantUsageByKey(tenantId, 'dailyActiveUser');
  // Example: enforce a 1,000 DAU limit
  return dailyActiveUser < 1000;
}

```

## Summary

- **Data Aggregation**: Logto stores raw sign-ins in `daily_active_user` and aggregates them nightly into `aggregated_daily_active_users` for efficient querying.
- **Database Indexes**: The migration at [`1.35.0-1764580589-create-aggregated-daily-active-users-table.ts`](https://github.com/logto-io/logto/blob/main/1.35.0-1764580589-create-aggregated-daily-active-users-table.ts) creates optimized indexes on tenant/date and tenant/user/date columns.
- **Metrics API**: The [`daily-active-user.ts`](https://github.com/logto-io/logto/blob/main/daily-active-user.ts) query module and [`dashboard.openapi.json`](https://github.com/logto-io/logto/blob/main/dashboard.openapi.json) endpoint expose DAU, WAU, MAU, and 30-day history.
- **Quota Enforcement**: The [`quota.ts`](https://github.com/logto-io/logto/blob/main/quota.ts) library provides memoized usage checks via `getTenantUsageByKey()` to enforce tenant limits without performance penalties.

## Frequently Asked Questions

### How does Logto calculate DAU, WAU, and MAU?

Logto calculates DAU by counting unique user IDs in the `aggregated_daily_active_users` table for a specific tenant and date. WAU and MAU use rolling 7-day and 30-day windows respectively, aggregating the daily counts stored in the table. The queries in [`packages/core/src/queries/daily-active-user.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/queries/daily-active-user.ts) perform these calculations using indexed SQL queries for sub-second response times.

### Where is tenant usage data physically stored?

Tenant usage data resides in two PostgreSQL tables: the raw `daily_active_user` table captures every sign-in event, while the `aggregated_daily_active_users` table stores pre-computed daily summaries. The schema is defined in [`packages/schemas/tables/aggregated_daily_active_users.sql`](https://github.com/logto-io/logto/blob/main/packages/schemas/tables/aggregated_daily_active_users.sql) and created via the migration file [`1.35.0-1764580589-create-aggregated-daily-active-users-table.ts`](https://github.com/logto-io/logto/blob/main/1.35.0-1764580589-create-aggregated-daily-active-users-table.ts).

### How can I check my tenant's current usage programmatically?

You can query the Dashboard API endpoint defined in [`packages/core/src/routes/dashboard.openapi.json`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/dashboard.openapi.json) using an API key, or import `getTenantUsageByKey` from [`packages/core/src/libraries/quota.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/quota.ts) within your Logto customization code. The API returns JSON with current DAU, WAU, MAU values and a 30-day history array.

### What happens when a tenant exceeds their usage quota?

When a tenant approaches or exceeds limits, the quota library in [`packages/core/src/libraries/quota.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/quota.ts) throws a quota-exceeded error that prevents the operation from completing. This enforcement happens automatically for protected resources, ensuring tenants cannot bypass their configured DAU or MAU limits.