Certificate expiration monitoring with Application Insights availability tests
A Standard availability test can watch a certificate for you: turn on Enable SSL certificate validity and set a Proactive lifetime check in days, and the test starts failing that many days before the certificate expires, so the availability alert fires while there's still time to renew. The check covers only the final URL after redirects, the endpoint must be reachable from the public internet, and each run costs a fraction of a cent. URL ping tests, which can't do this, are deprecated and are removed on September 30, 2028.
Expired certificates cause outages that nobody’s monitoring catches until users do: the app is healthy, the servers are fine, and every browser refuses to connect. An availability test that checks the certificate’s remaining life turns a hard deadline into an ordinary alert, weeks ahead.
What a Standard test checks
Standard tests send one request from each chosen location on a schedule and validate the response. Beyond reachability and timing, they can check:
- SSL certificate validity: that the certificate is installed correctly, valid, trusted and doesn’t produce errors for users. Only the certificate on the final redirected URL is checked; the test follows up to 10 redirects.
- Proactive lifetime check: a number of days before expiry at which the test starts failing. In templates it’s
SSLCertRemainingLifetimeCheck, which must be positive and requiresSSLCheckto be true. - HTTP verb, headers and body, so you can test a
HEADor aPOSTendpoint. - Success criteria: the expected status code, a timeout, and an optional case-sensitive content match.
The limits are 100 tests per Application Insights resource, up to 16 locations, and a minimum frequency of five minutes; checks more frequent than that need a custom approach. Microsoft recommends at least five locations so you can tell a site problem from a network problem, and retries on, because about 80% of failures disappear on retry: with retries, a location reports failure only after three successive attempts fail.
Create the test
In the portal, open the resource’s Availability page, select Add Standard test, enter the URL, tick Enable SSL certificate validity, set Proactive lifetime check, pick five or more locations and create it.
The same test as Bicep, for every certificate you own (one resource per URL; hidden-link ties it to the Application Insights resource):
resource certTest 'Microsoft.Insights/webtests@2022-06-15' = {
name: 'cert-www-contoso-com'
location: location
kind: 'standard'
tags: { 'hidden-link:${appInsights.id}': 'Resource' }
properties: {
Name: 'cert-www-contoso-com'
SyntheticMonitorId: 'cert-www-contoso-com'
Kind: 'standard'
Enabled: true
Frequency: 900 // seconds; a certificate doesn't need 5-minute checks
Timeout: 30
RetryEnabled: true
Locations: [ { Id: 'us-tx-sn1-azr' } /* add at least four more location IDs */ ]
Request: { RequestUrl: 'https://www.contoso.com/', HttpVerb: 'HEAD', ParseDependentRequests: false, FollowRedirects: true }
ValidationRules: {
ExpectedHttpStatusCode: 200
SSLCheck: true
SSLCertRemainingLifetimeCheck: 14
}
}
}
A 15-minute frequency is plenty for a check whose answer changes once a day, and it cuts the cost by two-thirds compared with the five-minute default.
Alert on it
Availability tests come with an alert rule, enabled by default, that fires when a number of locations report failures. Two settings matter:
- Alert location threshold. Microsoft’s rule of thumb is the number of test locations minus two, with at least five locations, so 3 of 5.
- Action group. Without one, the rule only shows in-portal notifications. Open the test’s context menu, select Open Rules (Alerts) page, edit the rule, and set severity, description and an action group.
These alerts are state based: one email when the test starts failing and one when it passes again, not a reminder every evaluation. For a certificate that’s the right behaviour, and the description field is the place to write who renews it and how. For more control (longer aggregation periods, other operators) create a custom metric alert on the Availability metric, or a log search alert over availabilityResults; Azure Monitor alerts explained walks through both.
When the alert fires, open the test’s results and select a failed run on the scatter plot. The end-to-end transaction view includes a troubleshooting report on what failed and shows the response the agent received, which is quicker than reproducing the check by hand. If you own many hostnames, give each its own test; with the 100-test limit per resource, group certificate tests in a dedicated Application Insights resource rather than crowding the one your app’s own tests use.
Behind a firewall
The test agents run from Microsoft’s shared IP ranges. To let them in, allow the ApplicationInsightsAvailability service tag on ports 80 and 443, and because those addresses are shared with other customers’ tests, also check a header: add X-Customer-InstanceId with the value ApplicationInsightsAvailability:<your identifier> to the test and reject requests without it. The site needs a public DNS record either way. On the TLS side, test agents use TLS 1.2 and 1.3 with modern cipher suites only; legacy suites and curves have been blocked since May 1, 2025, so a server that only offers them fails the test even with a valid certificate.
What it costs
Standard tests are billed per execution. The Azure Retail Prices API lists the Standard Web Test Execution meter at $0.0005 per run in East US. A test every 5 minutes from 5 locations runs 1,440 times a day, about 43,200 times a month: $21.60. At 15 minutes it’s $7.20 a month. Results are stored in availabilityResults like any other telemetry.
Classic SDK 2.x
Before Standard tests, the common answer was a URL ping test plus custom code. URL ping tests can’t check certificates, are deprecated, and existing ones are removed on September 30, 2028, after Microsoft extended the original 2026 date by 24 months; the portal has a migration path to Standard tests.
The custom route is TelemetryClient.TrackAvailability(), usually from a timer-triggered function that runs your own check and reports an AvailabilityTelemetry with a name, run location, duration, success flag and message. Microsoft now files this under archived Classic API guidance and says Standard tests should always be used if possible, because custom tests are code you have to maintain.
A custom check in a timer function that fails 14 days before a certificate expires, reported with the 2.x SDK:
var started = DateTimeOffset.UtcNow;
var timer = Stopwatch.StartNew();
bool ok = false; string message = "";
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (req, cert, chain, errors) =>
{
var daysLeft = (cert!.NotAfter.ToUniversalTime() - DateTime.UtcNow).TotalDays;
ok = errors == SslPolicyErrors.None && daysLeft > 14;
message = $"{daysLeft:F0} days left, errors: {errors}";
return true; // let the request finish; the result is reported below
}
};
using (var http = new HttpClient(handler))
{
await http.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://internal.contoso.local/"));
}
telemetryClient.TrackAvailability("cert internal.contoso.local", started, timer.Elapsed,
Environment.GetEnvironmentVariable("REGION_NAME") ?? "office", ok, message);
telemetryClient.Flush();
That’s the case where custom code earns its keep: an internal endpoint a Standard test can’t reach.
Today: SDK 3.x and the Microsoft OpenTelemetry Distro
SDK 3.x keeps TrackAvailability; only the overload that took a metrics dictionary was removed, so the snippet above works after an upgrade. The Microsoft OpenTelemetry Distro has no availability API: Microsoft’s table of custom telemetry the OpenTelemetry APIs can send doesn’t include availability results. From a Distro-instrumented app or a plain script, either keep a Standard test, or post an AvailabilityData item directly, as shown in sending telemetry with one request.
Query the results
Availability per test and location over the last week, using Microsoft’s own success calculation:
availabilityResults
| where timestamp > ago(7d)
| summarize runs = sum(itemCount),
availabilityPct = round(sum(todouble(success == 1) * 100) / count(), 2),
lastMessage = take_any(message)
by name, location
| order by availabilityPct asc
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Test passes but the certificate is about to expire | Proactive lifetime check not set, or SSL validity off | Turn on both |
| Test fails for a valid certificate | Server offers only legacy TLS ciphers or curves | Enable TLS 1.2 or 1.3 with modern suites |
| Wrong certificate checked | Redirect to another host | Test the final host directly |
| No email when the test fails | No action group on the alert rule | Edit the rule and add one |
| Alerts from a single location | Location threshold too low | Use locations minus two, at least 3 of 5 |
| Internal site always fails | Not reachable from the internet | Allow the service tag and header, or use a custom check |
Queries for this topic
-
Availability results by test and location
availabilityResults availability
Returns: One row per availability test and test location with the number of runs, the failed runs, the availability percentage and the p95 test duration in milliseconds, worst first.
-
Availability test failures with their messages
availabilityResults availability
Returns: Up to 100 failed availability test runs from the last 24 hours, newest first, each with the test name, location, duration in milliseconds, failure message and operation_Id.
Frequently asked questions
Does the certificate check look at intermediate certificates or every redirect?
Microsoft documents that the test validates the certificate on the final redirected URL only, and that it checks the certificate is installed correctly, valid and trusted. If a redirect goes through another host, give that host its own test.
How many days should the proactive lifetime check use?
Longer than your renewal process takes, including approvals and the time to deploy. If renewing and rolling out a certificate takes a week, a 14-day check leaves a margin. The test fails from that day on, so the alert keeps reminding you until it's fixed.
Can I monitor a certificate on an internal endpoint?
Not with a Standard test unless the endpoint is reachable from the public internet, possibly restricted to the ApplicationInsightsAvailability service tag. For private endpoints, Microsoft suggests an internal health signal with log or metric alerts, or a custom check that reports its own availability results.
Sources, checked
- Application Insights availability tests
- Microsoft.Insights webtests (Bicep and ARM template reference)
- Metrics in Application Insights (availability metrics and queries)
- Azure Monitor service limits (availability tests)
- Azure Retail Prices API, Standard Web Test Execution (East US)
- Custom availability tests with TrackAvailability (Classic API 2.x, archived)
- Breaking changes: Application Insights 2.x to 3.x (TrackAvailability)