Monitoring Tenant Usage and Daily Active Users in Logto: A Complete Technical Guide
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. 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 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 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. 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 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:
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:
pnpm cli daily-aggregation run
Checking Quotas Programmatically
Integrate quota checks into your custom logic using the quota library:
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_userand aggregates them nightly intoaggregated_daily_active_usersfor efficient querying. - Database Indexes: The migration at
1.35.0-1764580589-create-aggregated-daily-active-users-table.tscreates optimized indexes on tenant/date and tenant/user/date columns. - Metrics API: The
daily-active-user.tsquery module anddashboard.openapi.jsonendpoint expose DAU, WAU, MAU, and 30-day history. - Quota Enforcement: The
quota.tslibrary provides memoized usage checks viagetTenantUsageByKey()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 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 and created via the migration file 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 using an API key, or import getTenantUsageByKey from 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →