Opsgenie shuts down April 2027 - migrate to Pagerly in one click
PagerlyPagerly
← All postsEngineering

SSL Certificate Expiry Alerts in Slack

Set up SSL certificate expiry alerts that reach the on-call engineer: tiered thresholds, openssl checks, and CT log discovery.

SSL Certificate Expiry Alerts in Slack

Certificate expiry is the most predictable outage in all of infrastructure. The date is printed inside the certificate. You can read it ninety days ahead. Nothing about it is a surprise, and yet SSL certificate expiry alerts remain one of the most common gaps in otherwise mature monitoring setups, and expired certificates keep taking down production systems at companies with serious engineering teams.

The reason is rarely that nobody knew certificates expire. It is that the warning went to a place nobody was looking, or the renewal automation failed silently weeks earlier, or the certificate that broke was one nobody knew existed. This guide covers what to actually monitor, the tiered alert schedule that gets a response instead of a shrug, how to check expiry from the command line, and how to get the alert in front of the person on call rather than into a shared inbox. If you want the broader landscape of tooling first, our post on SSL certificate monitoring tools and practices covers that ground.

Why Certificate Expiry Still Causes Outages

Renewal Automation Fails Quietly

Most teams solved certificate renewal years ago by automating it, and that automation is genuinely reliable right up until it is not. An ACME client stops renewing because a validation record changed, a firewall rule broke the challenge, a rate limit was hit, or a cron job silently stopped running. None of these produce an alert, because the failure mode is a renewal that did not happen rather than an error that did.

The certificate then sits there, valid, counting down. Everything looks fine for weeks. The first symptom is total TLS failure at the moment of expiry, usually affecting every client at once. This is the single most common path to a certificate outage, and it is why monitoring renewal success matters as much as monitoring the expiry date.

The Certificates Nobody Owns

Public web certificates get attention. The ones that cause incidents are usually elsewhere:

  • Internal service certificates behind a load balancer, where the external certificate is fine and the internal leg quietly expires
  • Client certificates for mutual TLS, which expire on their own schedule and break integrations rather than websites
  • Certificates on non HTTP services: SMTP, LDAP, message brokers, database connections
  • Intermediate certificates in a chain that was assembled manually and never revisited
  • Code signing and push notification certificates, which break releases rather than serving traffic
  • Certificates on appliances, VPN concentrators and vendor managed boxes nobody has logged into in a year

The Notification Went Nowhere Useful

Certificate authorities send expiry reminders by email, to the address on the account. That address is frequently a shared alias, or an individual who has since left, or a distribution list that routes to a folder. CA reminder emails are a genuinely useful backstop and a genuinely terrible primary alerting mechanism, because there is no acknowledgement, no escalation and no way to tell whether anyone read them.

Certificate Lifetimes Are Shrinking Fast

This is the part that turns a manageable annoyance into a real operational problem. In April 2025 the CA/Browser Forum approved ballot SC-081v3, which phases maximum TLS certificate validity down on a fixed schedule: 200 days from 15 March 2026, 100 days from 15 March 2027, and 47 days from 15 March 2029. The period during which domain validation information can be reused drops to 10 days at the same endpoint.

The practical consequence is that manual renewal stops being viable. A 47 day certificate needs renewing roughly eight times a year, per certificate. Any process that involves a human remembering something will fail. Automation becomes mandatory, and once it is mandatory, monitoring the automation becomes mandatory too.

What To Actually Monitor

Days Remaining On The Live Endpoint

Check the certificate that is actually being served, not the one in your configuration management or your certificate store. These diverge more often than you would expect: a renewal succeeds, writes a new certificate to disk, and the service is never reloaded, so the old certificate keeps being served until it expires. Config says renewed. Reality says otherwise. Only an external check against the live endpoint catches this.

The Full Chain, Not Just The Leaf

A certificate chain is only as valid as its weakest link. Verify the intermediate certificates too, and verify that the chain your server presents is complete. Incomplete chains are especially nasty because they often work in browsers, which cache intermediates, while failing in command line clients, mobile apps and server to server calls. The bug report arrives as "the API is broken for some customers" and takes hours to trace back to TLS.

Every Port, Not Just 443

Scan the ports that actually terminate TLS across your estate. Mail on 465 and 587, LDAPS on 636, database ports, broker ports, admin interfaces on non standard ports. A monitoring setup that only checks 443 will miss most of the certificates capable of causing an incident.

Renewal Pipeline Health

Monitor the renewal process as a job in its own right, independent of the expiry date. If renewal is supposed to run weekly, alert when it has not reported success in that window. This is the check that gives you weeks of warning rather than days, because it fires when renewal breaks, not when the certificate is nearly dead.

A Tiered Alert Schedule That Gets A Response

The instinct is to set one alert at some comfortable threshold, often thirty days. This does not work, for a reason that has nothing to do with certificates: a single alert thirty days before a deadline arrives at a moment when it is not urgent, gets acknowledged, and is then forgotten. Thirty days later the certificate expires and everyone is surprised.

Tiering solves it by escalating both the urgency and the audience as the deadline approaches:

  • 45 days out: informational. Create a ticket, assign an owner. No notification to anyone on call. At this range you are confirming automation is working, not asking for action.
  • 21 days out: a notification in the owning team's channel. Something is not renewing as expected and needs a human to look during working hours.
  • 10 days out: escalate to the team lead or service owner by direct mention. The automated path has clearly failed and manual renewal needs scheduling now.
  • 5 days out: page the on call engineer during working hours. This is now an incident in slow motion.
  • 48 hours out: page immediately, regardless of hour, and open an incident. At this point the outage is scheduled and you know exactly when it starts.

Tune the top of the range to your renewal lead time. With 47 day certificates arriving in 2029, a 45 day first alert becomes meaningless, so the whole ladder compresses: informational at 20 days, page at 3. Build the thresholds as a proportion of the certificate's lifetime rather than fixed day counts, and the schedule keeps working as lifetimes shrink.

Checking Expiry From The Command Line

For a single host, openssl gives you the dates directly:

echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

The -servername flag matters. Without it you are not sending SNI, and on shared infrastructure you will get back a default certificate rather than the one you meant to check. This is a common source of confusing results.

To get days remaining as a number you can alert on, check whether the certificate will still be valid at a future point:

openssl x509 -noout -checkend 604800

That returns success if the certificate is valid for at least another seven days, expressed in seconds, and failure otherwise. It is a clean building block for a monitoring check because it gives you a simple exit code.

To verify the chain rather than just the leaf, add verification and read the result:

echo | openssl s_client -servername example.com -connect example.com:443 -verify_return_error

Wrap whichever form you use in a loop over an inventory file, and you have a working check in a dozen lines. The hard part was never the checking. It is the inventory and the routing.

Building An Inventory You Can Trust

You cannot monitor certificates you do not know about, and every organisation has more than it thinks. Three sources together get you close to complete coverage:

  • Certificate Transparency logs. Every publicly trusted certificate issued for your domains is recorded in public CT logs. Searching them for your domains surfaces certificates issued by teams who never told anyone, including ones issued by a vendor on your behalf. This is the highest yield discovery method available and it costs nothing.
  • Scan your own address space. CT logs will not show internal or privately issued certificates. A periodic scan across your internal ranges and known ports finds those.
  • Infrastructure as code. Anything defined in Terraform or similar should register its certificate into the monitoring inventory as part of provisioning, so new services are covered from the day they launch rather than the day someone remembers.

Attach an owning team to every entry. An alert about a certificate with no owner is an alert that will bounce around until it expires.

Getting The Alert Where Someone Will See It

Every piece of this is straightforward until the last step, which is the one that determines whether any of it mattered. An alert that fires correctly into a channel nobody reads is indistinguishable from no alert at all.

Email fails here for structural reasons. There is no acknowledgement, so you cannot tell the difference between handled and ignored. There is no escalation, so a missed message stays missed. And certificate warnings look exactly like every other automated email, which is to say they look like something to deal with later.

What works is routing by responsibility rather than by topic. The alert should name the person currently on call rather than mentioning a channel, because an alert addressed to everyone is addressed to nobody. It should arrive in the tool the team already has open. And past a certain threshold it should escalate if nobody acknowledges, because people miss things.

This is what Pagerly's uptime monitoring and paging handle together. Monitors check the endpoints you register, alerts land in Slack or Discord, and the paging path escalates through email, SMS, phone call and the mobile app when a page goes unacknowledged. Because the on call schedule lives in the same place through rotations in Slack, the alert follows the current shift rather than whoever was configured months ago. For the low urgency end of the ladder, task management in Slack turns a 45 day warning into an assigned, tracked item instead of a message that scrolls away.

The Runbook For A Certificate That Already Expired

Alerts fail sometimes, and eventually someone will be looking at an expired certificate in production. Having the steps written down in advance turns a frantic hour into a fifteen minute fix, so attach this to the paging alert.

Confirm What Actually Expired

Check the live endpoint rather than trusting the alert, using the s_client command above. Establish whether the expired certificate is the leaf or an intermediate, because the fix differs. An expired intermediate means the chain your server is sending is stale even though the leaf is fine, and the remedy is to update the chain file rather than to reissue anything.

Check Whether A Valid Certificate Is Already On Disk

Surprisingly often the renewal worked and the reload did not, which means a valid certificate is sitting on the filesystem while the process serves the old one from memory. This is the single most common cause and the fastest fix. Inspect the certificate file's dates directly, and if it is current, reload the service and you are done.

Reissue If You Must, With Rate Limits In Mind

If renewal genuinely failed, issue a new certificate. Be aware that ACME providers enforce rate limits, and a panicking engineer running the renewal repeatedly can exhaust the limit and lock themselves out for hours. Run it once, read the error properly, and fix the underlying validation problem rather than retrying.

Deploy Everywhere The Certificate Lives

Certificates are frequently installed in more than one place: several load balancer nodes, a CDN configuration, a container image, a secrets store. Replacing it in one location and reloading one node produces an intermittent failure that is harder to diagnose than the original outage, because roughly half of requests will succeed.

Then Fix The Monitoring

An expired certificate in production is by definition a monitoring failure as much as a renewal failure. Before closing the incident, establish why no alert fired. The usual answers are that the certificate was not in the inventory at all, or the alert went to a channel nobody watches. Both are fixable in minutes while the incident is fresh, and neither gets fixed a week later.

Mistakes Worth Avoiding

  • Monitoring only the public website. The certificates that cause incidents are usually internal.
  • Checking config instead of the live endpoint. Misses the renewed but never reloaded case entirely.
  • Omitting SNI. You end up checking a default certificate and getting a reassuring answer about the wrong thing.
  • A single alert threshold. One warning at 30 days gets acknowledged and forgotten.
  • Relying on CA reminder emails. Useful backstop, hopeless primary.
  • No owner on the inventory entry. Unowned alerts do not get actioned.
  • Ignoring the renewal job. Watching only the expiry date throws away weeks of warning.
  • Fixed day thresholds. They stop making sense as certificate lifetimes shrink.

A Rollout That Takes An Afternoon

  • Pull your domains from CT logs and list every certificate found
  • Scan internal ranges for TLS on any port, not just 443
  • Merge into one inventory with an owning team per entry
  • Add a daily check against live endpoints, with SNI, verifying the full chain
  • Configure the tiered thresholds as proportions of certificate lifetime
  • Route the urgent tiers to the on call rotation, the low tiers to a tracked task
  • Add a separate check on renewal job success
  • Test by pointing a check at a deliberately short lived certificate and confirm each tier fires
  • Re run CT discovery monthly to catch newly issued certificates

The Takeaway

Certificate expiry is a solved problem that keeps causing outages because the solution has three parts and most teams implement one. Knowing the expiry date is easy. Knowing about every certificate you have is harder. Getting a human to act on the warning is the part that actually fails.

With validity periods dropping to 100 days in 2027 and 47 days in 2029, the margin for a process that depends on someone remembering is disappearing. Automate renewal, monitor the automation rather than just the date, discover certificates continuously through CT logs, and route the alerts to a named person who can acknowledge them. The checking is a one line openssl command. The routing is what keeps you online.

Want certificate warnings to reach whoever is on call instead of a shared inbox? Pagerly runs your monitors and your on call schedule in the same place, inside Slack, with escalation when nobody acknowledges. Get started free.