Log Analytics workspaces — design, table plans, retention, access control, daily cap, and querying from TypeScript

How to set up and query a Log Analytics workspace — start with one workspace, Analytics vs Basic vs Auxiliary table plans and what each gives up, 30-day default retention to two years interactive and 12 years total, workspace vs resource-context access and the Log Analytics roles, the daily cap that stops collection, query limits that return 429, partial results, and @azure/monitor-query-logs with Entra.

markdownreferencev1T4F5-GBEPstage: designtrust: officialservice: monitorinterface: sdkinterface: iacLog Analytics workspace designsingle workspacetable plans Analytics Basic AuxiliaryBasic logs 30 days queryretention 30 days default90-day default tablesanalytics retention two yearstotal retention 12 yearslong-term retention search jobsaccess control modeenableLogAccessUsingOnlyResourcePermissionsresource-contextworkspace-contextLog Analytics ReaderLog Analytics ContributorLog Analytics Data Readerworkspaces/query/readtable-level RBACdaily capdailyQuotaGbreset hourquery concurrency 5query 429200 queries per 30 secondsquery timeout 3 minutes 10 minutesPartialError@azure/monitor-query-logsLogsQueryClient queryWorkspaceLogsQueryResultStatus PartialFailureworkspace customerIdMicrosoft.OperationalInsights/workspaces disableLocalAuth

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

Log Analytics workspaces

Design

Start with one workspace (per Entra tenant); data volume doesn't slow queries. Split only for a real reason: data residency per region, egress cost, separate billing or commitment tiers, or resilience (ingest into workspaces in two regions). Workspace-based Application Insights, diagnostic settings and agents all write into it.

Table plans and retention

PlanForTrade-offs
AnalyticsMonitoring, alerts, latency-sensitive queriesFull features; highest ingestion cost
BasicTroubleshooting dataQueries billed; 30 days of query access; summary rules and resource-context queries limited
Auxiliary / LakeHigh-volume, verbose data kept cheaplyAlerts stop working on the table; queries billed
  • Tables keep data 30 days by default (some built-in tables 90). Analytics retention extends to two years; total retention (including low-cost long-term retention, reached through search jobs) to 12 years.
  • Shortening total retention waits 30 days before deleting, so a mistake can be reverted; lengthening applies to data not yet removed.

Access

  • Access control mode (features.enableLogAccessUsingOnlyResourcePermissions): Use resource or workspace permissions (true; the default since March 2019) lets anyone with read on a resource query that resource's logs in resource context; Require workspace permissions (false) needs a workspace or table role.
  • Roles: Log Analytics Reader (read data and monitoring settings), Log Analytics Contributor (also configure), Log Analytics Data Reader (minimum query rights; for granular, condition-based RBAC). Querying needs Microsoft.OperationalInsights/workspaces/query/read; resource-context needs Microsoft.Insights/logs/<table>/read.
  • Resource context works only for records with _ResourceId, only on Analytics tables, and for Application Insights only when it's workspace-based.
  • features.disableLocalAuth turns off the workspace's shared-key authentication.

Daily cap

A daily cap stops collecting billable data in Analytics and Basic tables until the workspace's reset hour (fixed per workspace, not configurable); some data beyond the cap still lands. It's a budget guard, not a cost-saving tool: alert on it, because monitoring and alerts go blind once it's reached.

Querying from TypeScript

import { DefaultAzureCredential } from "@azure/identity";
import { LogsQueryClient, LogsQueryResultStatus, Durations } from "@azure/monitor-query-logs";

const credential = new DefaultAzureCredential();

// Query: needs Log Analytics Reader (or table/resource-level read) on the workspace.
export async function failedRequests(workspaceId: string): Promise<void> {
  const logs = new LogsQueryClient(credential);
  const kql = "AppRequests | where Success == false | summarize failures = count() by bin(TimeGenerated, 5m) | order by TimeGenerated desc";
  const result = await logs.queryWorkspace(workspaceId, kql, { duration: Durations.oneHour }, { serverTimeoutInSeconds: 120 });
  if (result.status === LogsQueryResultStatus.Success) {
    for (const row of result.tables[0]?.rows ?? []) console.log(row);
  } else {
    // PartialFailure: some data came back (limits, timeouts); don't treat it as complete. Full failures throw.
    console.warn(result.partialError.code, result.partialError.message);
  }
}

workspaceId is the workspace's customer ID (a GUID), not its resource ID; use queryResource with a resource ID for resource-context queries.

Limit or errorDetail
Concurrency5 concurrent Analytics queries per user (2 for Basic/Auxiliary); more wait in a FIFO queue
429Queued over 3 minutes, more than 200 queued, or over 200 queries per 30 seconds per user
Timeout3 minutes by default, up to 10 (serverTimeoutInSeconds)
Partial resultsA non-fatal error during execution: HTTP 200 with tables plus an error of code PartialError; the SDK returns PartialFailure
Cross-resourceAt most 100 workspaces and Application Insights resources in one query

Read this document as markdown — the same bytes an agent receives.