Platform Documentation

Production engineering guide for platform documentation covering patterns, implementation strategies, and operational best practices.

Platform documentation in an engineering wiki is the structured, versioned, and discoverable body of reference material that describes how a platform is built, deployed, operated, and evolved. It matters whenever a team needs to understand a component without direct tribal knowledge, when onboarding new engineers, during incident triage, or before modifying platform infrastructure. Unlike narrative tutorials or marketing overviews, platform documentation focuses on concrete specifications: API schemas, resource definitions, deployment manifests, runbooks, and configuration boundaries. It is the difference between guessing how a service starts and reading the exact manifest that kubectl applies, or between hunting through chat history and finding the exact psql command that resets a feature flag.

Finding the Right Documentation

The first challenge is locating the authoritative source among potentially many files, repositories, or generated outputs. In a typical platform setup, documentation lives alongside code in the same version control system, often under a docs/ directory at the repository root. Use git to scope your search:

git log --all --oneline -- docs/ | head -20

This lists every commit that touched the documentation directory, ordered by recency. To see what changed in a specific file:

git log --follow -- docs/services/auth.md

If the platform publishes versioned references (e.g., OpenAPI or JSON Schema), those are usually tagged:

git tag --list 'v*' | sort -V
git show v1.4.2:docs/api/openapi.yaml

For platforms that expose machine‑readable descriptors over HTTP, a simple curl fetch can reveal the latest spec:

curl -sSL https://raw.githubusercontent.com/owner/repo/main/docs/api/openapi.json | jq '.info.version'

When documentation is split across multiple repositories or services, a centralized index—often a README.md at the root of a platform repo—maps component names to their doc paths. Treat that index as the single source of truth for navigation; if it diverges from the actual file layout, the index itself becomes the first point of failure.

Reading and Interpreting Platform Specs

Once the right file is located, the reader needs to extract the minimal information required to act. Real tools provide immediate, concrete output.

Kubernetes manifests are the most common spec format in platform engineering. To inspect the approved schema for a resource without applying it:

kubectl explain deployment.spec.replicas --default=1

The output is a human‑readable description of the field type, default, and whether it’s immutable. For a machine‑parseable view, the same command with --recursive prints the full JSON schema that kubectl internally uses:

kubectl explain deployment.spec --o=json | jq '.properties'

PostgreSQL platforms often rely on SQL schemas that double as documentation. To list all columns, their types, and constraints for a table:

psql -c "\d+ users"

Typical output includes column name, type, not‑null status, default, and any check constraints. If the platform uses role‑based access control, the same command reveals which columns are visible to the current user.

Raw HTTP APIs are frequently documented as OpenAPI or AsyncAPI files. To fetch the live description and inspect a single endpoint:

curl -sSL https://platform.example.com/v1/openapi.json | jq '.paths["/deployments"].get'

The returned JSON shape—summary, parameters, responses—is the exact contract the platform enforces. If the API returns a different shape, the documentation is out of sync with the running service.

Docker and container images often carry metadata in their LABEL instructions. To view the recorded version or build date from an image that’s already running on a host:

docker inspect my-platform-api --format='{{index .Config.Labels "build-version"}}'

This command prints the exact label value that was set during docker build. If the label is missing, the image was built without the agreed‑upon metadata pipeline, a common sharp edge.

Updating and Versioning Docs

Keeping documentation in sync with the platform is a persistent problem. The most reliable pattern is to treat docs as code: store them in the same repository as the manifests, schemas, or source they describe, and gate updates through the same CI/CD pipeline.

A typical workflow looks like this:

  1. Create a branch off the platform’s release line:
   git checkout -b docs/update-replicas
  1. Edit the manifest or schema file (e.g., change replicas: 2 to replicas: 3 in deployment.yaml).
  2. Commit and push; the CI pipeline runs a doc‑linter (often markdownlint or prettier) and, if the repo uses mkdocs or docfx, builds the site locally:
   mkdocs build
  1. Open a pull request. Reviewers must verify that the rendered output matches the intended change; if the linter flags a broken link or missing heading, the fix is applied before merge.

When the platform uses a GitOps operator (e.g., Argo CD or Flux), documentation can be synchronized automatically. The operator watches a Documentation custom resource and renders the site into a Kubernetes ConfigMap or Secret. An update to the source YAML triggers a new Documentation revision, which the operator pushes to the serving endpoint. The exact command to trigger a manual sync, if needed, is:

argocd app sync platform-docs

If the platform does not use GitOps, a simple make target often builds and publishes docs:

make docs-deploy

The Makefile typically runs mkdocs gh-deploy or docfx publish, pushing the generated static site to a gh-pages branch or a web‑root. Any deviation—such as a stale mkdocs.yml that references removed pages—will cause the build to fail with a clear error:

ERROR: Material reference 'services/auth.md' not found

Sharp operators know to treat such failures as signals that the source file was deleted or renamed without a corresponding index update.

Troubleshooting Documentation Failures

When a platform change produces unexpected behavior, documentation is often the first place investigators look—and the first place they’re misled.

Stale OpenAPI descriptions are a frequent root cause. A service may have added a new query parameter, but the published JSON file still lists the old set. A consumer reads the doc, builds a client, and receives 400 Bad Request because the server rejects the unfamiliar parameter. The error text typically reads:

{"error":"unexpected query parameter", "expected":["id","name"], "received":["id","name","status"]}

Re‑generating the spec from the server code (npm run generate-openapi) and overwriting the doc file resolves the mismatch.

Missing runbook cross‑references surface during incidents. A kubectl get pods output shows a container crashing with OOMKilled, but the wiki’s troubleshooting section only documents memory‑pressure handling for a different component. The operator spends twenty minutes grepping logs before realizing the correct runbook is under environment-management/network-timeouts.md. The silence of the wrong section is itself a failure mode: the doc exists, but it’s not the one the operator needs.

Authentication tokens embedded in documentation are a security sharp edge. A docker run command documented in the wiki might include --env API_TOKEN=abc123. If that repo is public, the token is compromised. The exact failure mode is not a service outage but a leaked secret that appears in CI logs, alerting tools, and eventually requiring rotation. The recommended pattern is to never commit secrets; instead, document the env var name only, and rely on the platform’s secret management (e.g., Kubernetes Secret or cloud‑native vault) to inject the value at runtime. A kubectl get secret check will confirm whether the secret exists:

kubectl get secret api-token -n platform -o yaml

If the output is Error: secrets "api-token" not found, the documentation references a missing resource, and the platform will either fall back to a default (often documented elsewhere) or reject the request outright.

Sharp Edges

Several failure modes are learned only after a production incident.

Error: PodSecurityPolicy "default" is deprecated in v1.28, use SecurityContextConstraints instead

The operator must cross‑reference the release notes and update the doc’s “migration” section. Until then, any attempt to apply a PSP manifest fails without obvious cause.

Understanding these edges comes from reading the exact error text, running the exact commands, and never assuming that a documented “default” applies outside its intended scope. Platform documentation that acknowledges these boundaries—listing the exact flag, the exact error, the exact config key—becomes a reliable operational tool rather than a decorative afterthought.

This page was rewritten on 18 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.