惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
腾讯CDC
G
Google Developers Blog
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
有赞技术团队
有赞技术团队
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
美团技术团队
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
"Confluence Docs Lie. Tie Your Documentation to Code Inst...
Kyryl · 2026-06-14 · via DEV Community

Every team has that Confluence page. The one that was carefully written to explain what the service does, what the API looks like, what each DB column means. Someone spent real time on it. It was accurate when it was written.

Six months later, it's fiction.

This isn't a discipline problem. I've seen it at teams with strong engineering culture, with good processes, with people who genuinely care about documentation. The Confluence page still goes stale. The root cause is structural, and until you treat it that way, nothing changes.

Why external docs always drift

When documentation lives in a different place than the code, there's no mechanism that forces them to stay in sync. It relies entirely on people remembering to update two separate things every time anything changes. A column gets renamed, an endpoint response adds a field, a Kafka message format evolves — the ticket gets closed, the code gets merged, and the Confluence page stays where it was.

AI writing more of your code makes this worse. More code ships faster now. The documentation debt compounds faster too.

The fix isn't better processes or more reminders in the PR template. It's to stop maintaining documentation as a separate artifact and tie it directly to the code.

Three tools that keep docs honest

Swagger on your REST controllers

If you're using Spring Boot with springdoc-openapi, you already have the infrastructure. You just need to use it properly.

@RestController
@RequestMapping("/api/orders")
@Tag(name = "Orders", description = "Order lifecycle management")
public class OrderController {

    @Operation(
        summary = "Get order by ID",
        description = "Returns a single order. 404 if the order doesn't exist or belongs to a different customer."
    )
    @ApiResponse(responseCode = "200", description = "Order found")
    @ApiResponse(responseCode = "404", description = "Order not found")
    @GetMapping("/{id}")
    public ResponseEntity<OrderDto> getOrder(
        @Parameter(description = "Internal order ID") @PathVariable Long id
    ) {
        return orderService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

The Swagger UI becomes a living contract. It's always current because it's generated from the code. Frontend devs, QA, external teams can check it themselves without asking you anything.

If your controllers are getting buried in annotations, the previous post on moving Swagger to interfaces covers that pattern.

PostgreSQL column comments in DDL

PostgreSQL supports COMMENT ON natively. It's been there forever, almost nobody uses it.

CREATE TABLE orders (
    id          BIGSERIAL    PRIMARY KEY,
    customer_id BIGINT       NOT NULL,
    status      VARCHAR(20)  NOT NULL,
    total_cents BIGINT       NOT NULL,
    created_at  TIMESTAMPTZ  NOT NULL DEFAULT now()
);

COMMENT ON TABLE orders IS 'Customer purchase orders. One row per order, regardless of item count.';

COMMENT ON COLUMN orders.status IS
    'Order lifecycle state. Valid values: PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED. '
    'Transitions are enforced in OrderService, not at the DB level.';

COMMENT ON COLUMN orders.total_cents IS
    'Order total in cents. Always positive. Divide by 100 for display. '
    'Never store as decimal — rounding bugs.';

These comments ship with the schema. They live in your migration files. When the column changes, the comment gets updated in the same commit, by the same person, in the same PR review.

You can query them directly:

SELECT
    c.column_name,
    pgd.description
FROM pg_catalog.pg_statio_all_tables AS st
JOIN pg_catalog.pg_description pgd ON pgd.objoid = st.relid
JOIN information_schema.columns c
    ON c.table_name = st.relname
    AND ordinal_position = pgd.objsubid
WHERE c.table_schema = 'public'
  AND c.table_name = 'orders';

And any decent DB client (DBeaver, DataGrip) surfaces them automatically when you hover over a column. No page to open. The schema explains itself.

doc attribute in Avro schemas

If you're using Avro for Kafka messages, the doc field is part of the spec. It's not optional in any meaningful sense if you care about your consumers understanding the contract.

{
  "type": "record",
  "name": "OrderCreatedEvent",
  "namespace": "com.example.events",
  "doc": "Published when a new order is placed. Consumed by inventory-service, billing-service, and notification-service.",
  "fields": [
    {
      "name": "orderId",
      "type": "long",
      "doc": "Internal order ID from the orders table."
    },
    {
      "name": "customerId",
      "type": "long",
      "doc": "References users.id. The customer who placed the order."
    },
    {
      "name": "totalCents",
      "type": "long",
      "doc": "Order total in cents. Always positive. Same semantics as orders.total_cents."
    },
    {
      "name": "status",
      "type": "string",
      "doc": "Initial status at publish time. Always PENDING for this event."
    }
  ]
}

When another team's developer needs to understand what this event carries, they read the schema. If the schema is registered in a Schema Registry (Confluent or otherwise), the docs are browsable there. No Confluence page, no hunting down who owns the topic.

Who else benefits

The obvious beneficiaries are engineers. Less time spent answering "what does this field mean" questions, better context when onboarding, less cognitive overhead when reading unfamiliar code.

But the compounding effect shows up with less technical people.

Give your BA a dump of the database DDL — just the schema files, no actual data. Or give them read-only access to a dev environment DB. With an AI assistant they can load those schemas and start asking questions: what do we store, what are the valid states for this field, how are orders and customers related. They get answers without pinging a developer. The schema is always current because it's in version control.

Same with Swagger. A product manager who can open Swagger UI and see the actual endpoints, parameters, and response shapes during a design discussion is a product manager who isn't blocked waiting for you to write up an email.

Your AI coding assistant also benefits. An LLM reading your schema with doc fields and COMMENT ON COLUMN entries has significantly more context than one reading bare column names. The quality of generated code improves with it.

The honest trade-off

Writing proper Swagger annotations, DDL comments, and Avro doc fields takes time upfront. Real time. When you're under pressure to ship the feature by Friday, adding good COMMENT ON COLUMN entries to the migration doesn't feel like a priority.

It's also harder to enforce than a Confluence page. With Confluence, you can at least point to a URL and say "write it here." With code-tied docs, you need to make it part of the review culture — PRs that add columns without comments don't get merged.

That's a real overhead, and I won't pretend otherwise.

But the alternative is paying that cost continuously. Every time someone joins the team and has to ask what a column means. Every time a BA opens a Jira ticket that could have been answered by looking at the schema. Every time your Confluence page sends someone down the wrong path because nobody updated it after the last refactor.

The upfront investment is a one-time cost per artifact. Stale docs are a recurring cost forever.

Write them once. Keep them with the code. They won't lie.


Do you have a practice for keeping docs in sync with code, or is it still Confluence pages and hope? Curious what's actually working at different team sizes.