Step 01 of 06
Learn the concept
Certificate expiry is the outage with a calendar invite that nobody accepted. Browsers reject the site instantly after NotAfter; users do not care that renewal almost worked. A monitor's job is to read the same clock while there is still time.
The ideas this is made of
A certificate is a signed, time-limited name binding
An X.509 certificate says a public key belongs to names such as example.com, and says who signed that claim. It also carries serial numbers, extensions, issuer data and a validity interval. During TLS, the client verifies signatures, hostname coverage and time validity before trusting the server. The certificate is not identity prose. It is a structured, signed contract.
NotAfter is the instant trust stops
NotBefore is the first valid instant. NotAfter is the last instant after which clients must reject the certificate. These are points in time, usually displayed in UTC. A certificate expiring at midnight UTC can appear to expire the previous evening elsewhere. Compute remaining time with time.Until(leaf.NotAfter), not by comparing local date numbers.
Expiry is a safety valve, not paperwork
Permanent certificates would let lost keys and obsolete algorithms live forever. Expiry limits the damage from an undiscovered private-key leak and forces rotation hygiene. Publicly trusted server certificates have been capped around 398 days, and the industry keeps pushing shorter. Short lifetimes make automation mandatory. They also make monitoring non-optional.
The leaf is common; intermediates are blast radius
The leaf certificate belongs to the server name and is PeerCertificates[0] in Go. Intermediates delegate signing power from a CA and may be shared across many sites. Roots are trust anchors in client stores and are usually not sent. A leaf expiry breaks one service. A bad intermediate can break a fleet that thought its leaves were fine.
Valid now and safe tomorrow are different facts
The TLS handshake decides whether this connection is acceptable now. Expiry monitoring asks how long remains before that answer changes. A cert with two days left may pass every browser check today and still deserve a page. Beacon records both: handshake success and days until NotAfter crosses the warning threshold.
package main
import (
"crypto/tls"
"fmt"
"log"
"time"
)
func main() {
conn, err := tls.Dial("tcp", "example.com:443", &tls.Config{
ServerName: "example.com",
})
if err != nil {
log.Fatal(err)
}
defer conn.Close()
certs := conn.ConnectionState().PeerCertificates
if len(certs) == 0 {
log.Fatal("server sent no certificates")
}
leaf := certs[0]
remaining := time.Until(leaf.NotAfter)
days := int(remaining.Hours() / 24)
fmt.Println("subject:", leaf.Subject.String())
fmt.Println("not_before:", leaf.NotBefore.UTC().Format(time.RFC3339))
fmt.Println("not_after:", leaf.NotAfter.UTC().Format(time.RFC3339))
fmt.Println("days_remaining:", days)
}Go verifies the certificate during the handshake, then exposes the verified peer chain. The example prints UTC instants and derives days from a duration, which is the calculation operators can trust across time zones.
Certificates in the chain
| Certificate | Where it lives | Failure shape |
|---|---|---|
Leaf | Sent by server first | One hostname fails |
Intermediate | Usually sent by server | Many leaves can fail |
Root | Client trust store | Platform-wide trust issue |
Clock | Client machine | Valid cert rejected |
What these are called on the job
Validity window — The interval from
NotBeforethroughNotAfterwhen trust is allowed.Subject alternative name — The extension listing DNS names and IPs the certificate covers.
Rotation — Replacing a certificate and usually its private key before trouble.
Leaf certificate — The server certificate for the hostname being contacted.
Intermediate — A CA certificate that delegates signing without exposing a root key.
