Building an OAuth2 Authorization Server from Scratch
Key Takeaways
- →Building an OAuth2 server from scratch teaches you why the spec requires PKCE and state parameters — you'll debug token failures instantly because you've seen the validation code
- →PKCE prevents authorization code interception by requiring the client to prove it initiated the request — SHA256(code_verifier) must match the stored code_challenge at token exchange
- →The JWKS endpoint at /.well-known/jwks.json exposes public keys for distributed signature verification without sharing secrets; key rotation happens transparently via key IDs
- →Refresh token rotation on every use enables theft detection — a stolen token becomes invalid immediately, signaling compromise and allowing revocation of the entire token family
The classic OAuth2-debugging-at-3 AM situation: your SPA stops logging users in. The token endpoint returns invalid_grant and the logs don't explain why. The client is sending a code_verifier, but you have no visibility into whether the PKCE validation passed server-side, which endpoint actually received it, or how your code_challenge comparison logic works. Hours later it turns out a misconfiguration sent requests to the wrong endpoint, the verifier landed somewhere it shouldn't, and the SHA-256 mismatch killed the entire flow. The fastest debugging path was rebuilding the server-side mental model from the RFC.
That's the point of this article: walk through OAuth 2.0[RFC 6749, 2012] and JWT[RFC 7519, 2015] from the server's perspective so you can debug client failures instantly.
This article builds a minimal OAuth2 authorization server for educational purposes. In production, use Keycloak, Auth0, Zitadel, or Dex. The value here is understanding how servers validate requests, issue tokens, and maintain security invariants so you debug failures intelligently.
Why Build One?
Most OAuth2 guides teach the client side. This article covers the server side: how the authorization server validates requests, issues tokens, and maintains security invariants.
Build a minimal OAuth2 server[RFC 6749, 2012] to understand why the spec requires PKCE, state parameters, and token rotation. You'll debug integration failures instantly and design better security boundaries.
- Implement the authorization endpoint with PKCE code_challenge validation
- Exchange authorization codes for signed JWTs[RFC 7519, 2015] via the token endpoint
- Expose public keys at /.well-known/jwks.json for distributed signature verification
sequenceDiagram
participant U as User
participant C as Client (SPA)
participant AS as Auth server
participant RS as Resource server
C->>C: gen code_verifier, code_challenge = SHA256 of verifier
U->>C: clicks "Sign in"
C->>AS: GET /authorize?client_id=&code_challenge=&state=
AS->>U: login + consent
U-->>AS: approve
AS-->>C: 302 redirect_uri?code=&state=
C->>AS: POST /token with code + code_verifier
AS->>AS: SHA256 of verifier == stored challenge?
alt match
AS-->>C: access_token JWT + refresh_token
else mismatch
AS-->>C: 400 invalid_grant 🔥
end
C->>RS: GET /api with Authorization: Bearer JWT
RS->>AS: GET /.well-known/jwks.json, cached
RS->>RS: verify JWT signature with public key
RS-->>C: 200 OK / 401
The diagram shows where every common OAuth2 failure surfaces: PKCE mismatch at the token endpoint, JWT signature verification at the resource server, and state validation on the redirect. If you can name the box that fired the error, you can fix it.
Understanding the server's perspective shows you why the documentation says what it says. You'll debug token validation failures instantly, understand why PKCE protects against interception, and integrate confidently with any identity provider.
The Quick Start
| Step | Endpoint | What it validates |
|---|---|---|
| 1. Authorization request | GET /oauth/authorize?client_id=...&code_challenge=... | Validates client_id, redirect_uri, PKCE code_challenge |
| 2. User consents | (Login + consent UI) | Authenticates user, confirms authorization scope |
| 3. Redirect to app | 302 redirect_uri?code=abc123&state=xyz | Code tied to client_id and code_challenge |
| 4. Token exchange | POST /oauth/token (code + code_verifier) | Verifies SHA256(code_verifier) == code_challenge, issues JWT + refresh |
| 5. Verify signature | GET /.well-known/jwks.json | Client fetches public key, validates JWT locally |
The client initiates → auth server generates a code → code is exchanged for a JWT → JWT is verified using the public key.
Key Generation and JWT Signing
The authorization server signs JWTs with an RSA private key. Clients verify signatures with the public key from the JWKS endpoint.
package authserver
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
)
// KeyManager handles RSA key generation and storage.
type KeyManager struct {
privateKey *rsa.PrivateKey
publicKey *rsa.PublicKey
keyID string
}
// NewKeyManager generates a fresh 2048-bit RSA key pair.
func NewKeyManager() (*KeyManager, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("key generation: %w", err)
}
return &KeyManager{
privateKey: privateKey,
publicKey: &privateKey.PublicKey,
keyID: "default-key",
}, nil
}
// ExportPublicKey returns the public key in PEM format for JWKS.
func (km *KeyManager) ExportPublicKey() (string, error) {
pubKeyBytes, err := x509.MarshalPKIXPublicKey(km.publicKey)
if err != nil {
return "", fmt.Errorf("marshal public key: %w", err)
}
pubKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: pubKeyBytes,
})
return string(pubKeyPEM), nil
}The Authorization Endpoint with PKCE
The full Authorization Code + PKCE flow in one picture — every arrow protects against a specific attack:
sequenceDiagram
participant App as Mobile/SPA app
participant AS as Auth server
participant U as User browser
participant API as Resource server
Note over App: Step 1 — generate PKCE pair
App->>App: code_verifier = random 43-128 chars<br/>code_challenge = SHA256 of verifier
Note over App,U: Step 2 — authorize
App->>U: redirect /authorize<br/>+ code_challenge + state
U->>AS: GET /authorize
AS->>U: login + consent UI
U->>AS: submit credentials
AS->>AS: validate, bind code to<br/>client_id + code_challenge
AS->>U: 302 redirect with code + state
U->>App: deliver code via custom URL scheme
Note over App,AS: Step 3 — exchange code for tokens
App->>AS: POST /token<br/>code + code_verifier
AS->>AS: SHA256 of verifier == challenge?<br/>code unused? not expired?
AS->>App: access_token + refresh_token
Note over App,API: Step 4 — call API
App->>API: GET /resource<br/>Bearer access_token
API->>API: validate JWT signature via JWKS
API->>App: protected data
The code_challenge / code_verifier handshake[RFC 7636 — PKCE] blocks the authorization-code interception attack: a malicious app on the same device can intercept the redirect, but it does not have the verifier — without it, the /token exchange fails.
The authorization endpoint validates the PKCE code_challenge and generates an authorization code tied to the client and code_challenge.
// AuthorizationRequest holds incoming authorization request parameters.
type AuthorizationRequest struct {
ClientID string
RedirectURI string
CodeChallenge string
CodeChallengeMethod string // "S256" (SHA256) or "plain"
State string // CSRF protection
}
// AuthorizationCode stores state needed for token exchange.
type AuthorizationCode struct {
Code string
ClientID string
RedirectURI string
CodeChallenge string
CodeChallengeMethod string
ExpiresAt time.Time
Used bool
}
// AuthorizationEndpoint validates the request and generates a code.
func (as *AuthServer) AuthorizationEndpoint(w http.ResponseWriter, r *http.Request) {
clientID := r.URL.Query().Get("client_id")
if clientID == "" {
http.Error(w, "missing client_id", http.StatusBadRequest)
return
}
redirectURI := r.URL.Query().Get("redirect_uri")
if redirectURI == "" {
http.Error(w, "missing redirect_uri", http.StatusBadRequest)
return
}
// PKCE: code_challenge is required
codeChallenge := r.URL.Query().Get("code_challenge")
if codeChallenge == "" {
http.Error(w, "PKCE code_challenge required", http.StatusBadRequest)
return
}
// Store the authorization code with PKCE challenge
code, err := generateRandomCode(32)
if err != nil {
http.Error(w, "server error", http.StatusInternalServerError)
return
}
authCode := AuthorizationCode{
Code: code,
ClientID: clientID,
RedirectURI: redirectURI,
CodeChallenge: codeChallenge,
CodeChallengeMethod: r.URL.Query().Get("code_challenge_method"),
ExpiresAt: time.Now().Add(10 * time.Minute),
Used: false,
}
as.storeAuthCode(code, authCode)
// Redirect back to the client with the code and state
state := r.URL.Query().Get("state")
redirectURL := fmt.Sprintf("%s?code=%s&state=%s", redirectURI, code, state)
http.Redirect(w, r, redirectURL, http.StatusFound)
}
func generateRandomCode(length int) (string, error) {
b := make([]byte, length)
// crypto/rand can fail; never ignore it — a short read would yield a
// weak or all-zero token. Propagate the error so the caller aborts.
if _, err := rand.Read(b); err != nil {
return "", fmt.Errorf("generate random code: %w", err)
}
return base64.RawURLEncoding.EncodeToString(b), nil
}The Token Endpoint: PKCE Verification and JWT Issuance
The token endpoint verifies the code and code_verifier match, then issues a signed JWT access token and a refresh token.
// TokenRequest holds the code exchange request.
type TokenRequest struct {
Code string
CodeVerifier string
ClientID string
}
// TokenResponse holds the issued tokens.
type TokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
}
// TokenEndpoint exchanges an authorization code for tokens.
func (as *AuthServer) TokenEndpoint(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "only POST allowed", http.StatusMethodNotAllowed)
return
}
code := r.FormValue("code")
codeVerifier := r.FormValue("code_verifier")
// Retrieve the authorization code
authCode, exists := as.getAuthCode(code)
if !exists || authCode.Used || authCode.ExpiresAt.Before(time.Now()) {
http.Error(w, "invalid or expired code", http.StatusBadRequest)
return
}
// PKCE verification: verify SHA256(code_verifier) == code_challenge
hash := sha256.Sum256([]byte(codeVerifier))
challenge := base64.RawURLEncoding.EncodeToString(hash[:])
if challenge != authCode.CodeChallenge {
http.Error(w, "PKCE verification failed", http.StatusBadRequest)
return
}
// Mark code as used (prevent replay attacks)
authCode.Used = true
as.storeAuthCode(code, authCode)
// Issue JWT access token
claims := jwt.MapClaims{
"sub": authCode.ClientID,
"aud": authCode.RedirectURI,
"iat": time.Now().Unix(),
"exp": time.Now().Add(1 * time.Hour).Unix(),
"scope": "read write",
}
accessToken, err := as.keyMgr.IssueJWT(claims)
if err != nil {
http.Error(w, "token issuance failed", http.StatusInternalServerError)
return
}
// Issue refresh token
refreshToken, err := generateRandomCode(64)
if err != nil {
http.Error(w, "token issuance failed", http.StatusInternalServerError)
return
}
as.storeRefreshToken(refreshToken, authCode.ClientID)
response := TokenResponse{
AccessToken: accessToken,
RefreshToken: refreshToken,
ExpiresIn: 3600,
TokenType: "Bearer",
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}The JWKS Endpoint for Public Key Distribution
The JWKS endpoint exposes the public key so resource servers verify JWT signatures without sharing secrets.
// JWKS represents the JSON Web Key Set response.
type JWKS struct {
Keys []JWK `json:"keys"`
}
// JWK represents a single JSON Web Key.
type JWK struct {
Kty string `json:"kty"` // "RSA"
Kid string `json:"kid"` // Key ID (matches JWT header "kid")
Use string `json:"use"` // "sig" for signing
N string `json:"n"` // RSA modulus (base64url)
E string `json:"e"` // RSA exponent (base64url)
}
// JWKSEndpoint serves the public keys at /.well-known/jwks.json.
func (as *AuthServer) JWKSEndpoint(w http.ResponseWriter, r *http.Request) {
pubKey := as.keyMgr.publicKey
n := base64.RawURLEncoding.EncodeToString(pubKey.N.Bytes())
e := base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pubKey.E)).Bytes())
jwk := JWK{
Kty: "RSA",
Kid: as.keyMgr.keyID,
Use: "sig",
N: n,
E: e,
}
response := JWKS{Keys: []JWK{jwk}}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}Refresh Token Rotation with Family Revocation
Long-lived refresh tokens are the highest-value target in any OAuth2 system. The defense is rotation with family revocation: every refresh issues a new refresh token AND invalidates the old one; if a revoked token is ever presented, you revoke the entire family on the assumption that the old token was stolen[RFC 6749, 2012].
// /token endpoint, grant_type=refresh_token branch
func handleRefresh(w http.ResponseWriter, r *http.Request, presented string) {
rt, err := store.LookupRefreshToken(r.Context(), presented)
if err != nil {
http.Error(w, "invalid_grant", http.StatusBadRequest)
return
}
// CRITICAL: presented token has already been used (rotated)
if rt.RotatedAt != nil {
// Theft detection: a revoked token was replayed.
// Revoke EVERY token issued to this user from this client.
_ = store.RevokeFamily(r.Context(), rt.UserID, rt.ClientID)
slog.Warn("refresh-token replay detected; family revoked",
"user", rt.UserID, "client", rt.ClientID)
http.Error(w, "invalid_grant", http.StatusBadRequest)
return
}
// Issue a new access token + new refresh token
newAT := signAccessToken(rt.UserID, rt.ClientID, rt.Scopes, 15*time.Minute)
newRT := generateRefreshToken()
if err := store.RotateRefreshToken(r.Context(), rt.ID, newRT, 30*24*time.Hour); err != nil {
http.Error(w, "server_error", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(map[string]any{
"access_token": newAT,
"refresh_token": newRT,
"token_type": "Bearer",
"expires_in": 900,
})
}The rotation invariant: at any moment, exactly one refresh token in the family is valid. Replay of any older token is treated as theft.
Production Checklist
- PKCE validation is mandatory for all public clients (mobile apps, SPAs, CLIs)
- Authorization codes expire in < 10 minutes and are single-use
- Access tokens include audience (
aud), subject (sub), and expiration (exp) claims - Refresh tokens are rotated on every use; revoke the entire token family if a revoked token is presented
- JWKS endpoint is cached (Cache-Control: max-age=86400) and signed responses are not cached
- Tokens are issued with short TTL (1–15 minutes for access, 7–30 days for refresh)
- Incoming requests are rate-limited per client_id to prevent brute-force attacks
- All endpoints enforce HTTPS (TLS 1.2+) and set security headers (HSTS, X-Frame-Options)
- Use a mature library (golang-jwt, jose4j, jsonwebtoken) instead of hand-rolling cryptography
Operational glue: rotation, revocation, and the audit log
The endpoints a from-scratch OAuth2 server gets right on the happy path but skips on the operational ones — key rotation, refresh-token-family revocation, and the audit log auditors will ask for. Together they're what keeps a hand-rolled IdP from becoming an incident generator.
Key rotation: ship the new key alongside the old one for a TTL window equal to your longest token lifetime, then retire the old one. The JWKS endpoint exposes both during the overlap so existing tokens keep verifying:
type SigningKeyStore struct {
mu sync.RWMutex
current *KeyPair // active for new tokens
retired *KeyPair // accepted on verify, not used for signing
}
// Rotate moves current → retired and brings in a new signing key.
// Retired key is dropped after the next rotation (TTL-based).
func (s *SigningKeyStore) Rotate(next *KeyPair) {
s.mu.Lock()
defer s.mu.Unlock()
s.retired = s.current
s.current = next
}
func (s *SigningKeyStore) JWKS() jose.JSONWebKeySet {
s.mu.RLock()
defer s.mu.RUnlock()
keys := []jose.JSONWebKey{s.current.public()}
if s.retired != nil {
keys = append(keys, s.retired.public())
}
return jose.JSONWebKeySet{Keys: keys}
}Refresh-token rotation with family revocation — the canonical defence against a stolen refresh token. If a previously-rotated token is presented (i.e., the attacker uses an old token while the legitimate user already rotated), revoke the entire chain:
-- refresh_tokens table — every refresh keeps the family ID across rotations
CREATE TABLE refresh_tokens (
id TEXT PRIMARY KEY,
family_id TEXT NOT NULL,
user_id BIGINT NOT NULL,
parent_id TEXT, -- chain back to predecessor
issued_at TIMESTAMPTZ NOT NULL DEFAULT now(),
expires_at TIMESTAMPTZ NOT NULL,
revoked_at TIMESTAMPTZ
);
CREATE INDEX rt_family_idx ON refresh_tokens (family_id);The handler that detects replay and nukes the family — this is what the OAuth2 spec calls "automatic reuse detection":
func (s *TokenServer) Refresh(ctx context.Context, presented string) (*TokenPair, error) {
rt, err := s.repo.GetByID(ctx, presented)
if err != nil { return nil, ErrInvalidGrant }
if rt.RevokedAt.Valid {
// Replay of a revoked token. Nuke the entire family — the legitimate
// owner will be forced to re-authenticate, which is the correct
// outcome when a token is suspected stolen.
_ = s.repo.RevokeFamily(ctx, rt.FamilyID)
s.audit.Log(ctx, AuditEvent{
Type: "refresh_token_replay",
FamilyID: rt.FamilyID,
UserID: rt.UserID,
})
return nil, ErrInvalidGrant
}
// Mark this rotation step revoked, mint successor in same family.
return s.rotate(ctx, rt)
}The audit-log schema — append-only with content-hash chaining so any tampering is detectable on the hash chain:
CREATE TABLE auth_audit (
id BIGSERIAL PRIMARY KEY,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
event_type TEXT NOT NULL,
actor_user_id BIGINT,
client_id TEXT,
ip INET,
user_agent TEXT,
context JSONB NOT NULL,
-- Each row's hash includes the previous row's hash; tamper-detection chain.
row_hash BYTEA NOT NULL,
prev_row_hash BYTEA NOT NULL
);
-- Single index covers the two queries auditors actually run.
CREATE INDEX auth_audit_actor_time ON auth_audit (actor_user_id, occurred_at DESC);The single most common mistake teams make on a hand-rolled IdP: skipping the audit log because "we'll add it later when we have a use case." The use case is always the same — six months in, a customer reports unauthorized access and you need to reconstruct the auth events leading up to it. Without the chain, you cannot prove whether your IdP issued the token or whether the row was modified after the fact.
Token Revocation Endpoint (RFC 7009)
Rotation handles the silent case — a refresh token replayed by an attacker. Explicit revocation handles the loud case — a user signs out, an admin disables an account, or a security tool spots a leaked credential and needs to kill the token immediately. Both paths exist for a reason and a production server has to implement both.
The revocation endpoint defined by RFC 7009 accepts a token plus an optional token_type_hint and returns 200 OK whether the token existed or not. The response is deliberately uniform so an attacker probing for valid tokens cannot distinguish "revoked successfully" from "never existed." Teams new to the spec usually get this wrong — they return 404 for unknown tokens and turn the endpoint into an oracle.
The wire format is a standard form post:
POST /oauth/revoke HTTP/1.1
Host: auth.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
token=2YotnFZFEjr1zCsicMWpAA&token_type_hint=refresh_tokenThe handler resolves the token, revokes the entire family if it is a refresh token (because revoking a single rotation step is meaningless — the family is the security unit), and writes an audit row. Crucially it never branches its response on whether the token was found:
// RevokeEndpoint implements RFC 7009. Always returns 200 to avoid
// leaking whether the token exists.
func (s *AuthServer) RevokeEndpoint(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "only POST allowed", http.StatusMethodNotAllowed)
return
}
clientID, clientSecret, ok := r.BasicAuth()
if !ok || !s.clients.Authenticate(r.Context(), clientID, clientSecret) {
// 401 is the only error the spec permits — auth failure.
w.Header().Set("WWW-Authenticate", `Basic realm="oauth"`)
http.Error(w, "invalid_client", http.StatusUnauthorized)
return
}
presented := r.FormValue("token")
hint := r.FormValue("token_type_hint")
// Resolve in hint order, fall back to the other type. Spec requires
// we accept either type regardless of hint.
rt, found := s.lookupForRevoke(r.Context(), presented, hint)
if found {
if rt.Kind == KindRefresh && rt.ClientID == clientID {
_ = s.repo.RevokeFamily(r.Context(), rt.FamilyID)
} else if rt.Kind == KindAccess && rt.ClientID == clientID {
_ = s.repo.RevokeAccessToken(r.Context(), rt.ID)
}
s.audit.Log(r.Context(), AuditEvent{
Type: "token_revoked", FamilyID: rt.FamilyID,
ClientID: clientID, UserID: rt.UserID,
})
}
// Always 200 — even if the token didn't exist or belonged to another client.
w.WriteHeader(http.StatusOK)
}The two security invariants worth emphasising: the endpoint enforces client authentication (a stolen token is not enough — the attacker needs the client credentials to revoke it), and it scopes revocation to tokens issued for the calling client. A multi-tenant server that lets one client revoke another's tokens is a denial-of-service vector.
Resource servers also need a story for revoked-but-still-unexpired access tokens. JWTs are stateless — once issued, they verify until exp regardless of revocation state. Two pragmatic options: keep access-token TTLs short enough that revocation latency is acceptable (1–15 minutes is typical), or maintain a revocation cache that resource servers consult on a sampled basis. The schema below holds the cache; the index on expires_at lets a background job evict rows once the underlying token would have expired anyway:
CREATE TABLE revoked_tokens (
jti TEXT PRIMARY KEY, -- JWT ID claim
family_id TEXT, -- null for access tokens
revoked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
expires_at TIMESTAMPTZ NOT NULL, -- original token exp
reason TEXT NOT NULL -- 'user_logout' | 'admin_disable' | 'leak_detected'
);
CREATE INDEX revoked_tokens_expiry ON revoked_tokens (expires_at);
-- Background job: evict rows whose underlying token has already expired.
DELETE FROM revoked_tokens WHERE expires_at < now() - INTERVAL '1 hour';Resource servers query revoked_tokens by jti on every request — a single indexed lookup, easily cached for the token's remaining TTL. The 1-hour grace window in the eviction query is paranoia: it covers clock skew between the auth server and resource servers so a token isn't accepted because the revocation row was deleted half a second too early.
Frequently Asked Questions
What is PKCE and why is it required for OAuth2?
PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks by requiring the client to prove it initiated the original authorization request. The client sends a hashed code_challenge during authorization and the original code_verifier during token exchange — the server verifies SHA256(code_verifier) matches the stored challenge.
How does a JWKS endpoint work in OAuth2?
The JWKS (JSON Web Key Set) endpoint at /.well-known/jwks.json exposes the authorization server's public keys so resource servers can verify JWT signatures without sharing secrets. Each key includes a key ID (kid) that matches the kid header in issued JWTs, enabling key rotation without invalidating existing tokens.
Why should you rotate refresh tokens on every use?
Rotating refresh tokens on every use enables theft detection. If a stolen refresh token is used, the legitimate client's next request will present an already-revoked token, signaling a compromise. The server then revokes the entire token family, limiting the attacker's window.
Should I build my own OAuth2 authorization server?
No — use a mature identity provider like Keycloak, Auth0, or Zitadel for production. Building one is valuable for understanding how authorization servers validate requests, issue tokens, and maintain security invariants, which helps you integrate and debug real providers.
Keep Reading
- OAuth2 and OpenID Connect Security Guide — Client-side OAuth2 flows, token validation, and security pitfalls
- Production Go API Design — Authentication middleware, JWT validation, and request signing patterns for production HTTP services
- Securing AI Agent Infrastructure — Applying these OAuth2 and token-handling patterns to LLM tool calls and agent authorization
- Distributed Rate Limiting — Rate-limit the /token endpoint to prevent brute-force attacks against client_id
- Building Resilient Distributed Systems with Go — Circuit breakers around the JWKS endpoint so token validation fails fast rather than hanging
Engineering Team
A multidisciplinary team of backend engineers, architects, and DevOps practitioners shipping deep dives into distributed systems and production infrastructure.
Read Next
OAuth2 and OpenID Connect: Production Security Patterns
OAuth2 flows with PKCE, refresh token rotation, theft detection, and JWT vs opaque token security tradeoffs for production.
Go context.Context Cheat Sheet: Cancellation, Timeouts & Gotchas
Go context.Context: constructors, cancellation, deadlines, request values, and five goroutine leak patterns in production.
Go Dynamic JSON: Parsing Unknown Schemas in Production
Handle unpredictable JSON in Go: map[string]any, json.RawMessage, type switches, and defensive patterns for shifting schemas.