1. Store Object Keys, Not File URLs

    Design file uploads around stable object keys, server-composed delivery URLs, collision-resistant names, and separately retained original filenames.

  2. Model Drafts by Meaning: Status or Separate Storage?

    Choose a status for ordinary lifecycle stages and separate versioned storage for distinct preparatory data, based on domain meaning and compatibility cost.

  3. Break Sequential ID Links in Anonymous Services

    Use independent random identifiers for identity-related records to remove obvious sequential links, while recognizing that UUIDs alone cannot guarantee anonymity.

  4. Oracle to MySQL Migration with Adapters, Dual Writes, and Flags

    A reversible Oracle-to-MySQL migration using compatible adapters, dormant deployments, dual writes, tested switches, deliberate rollback, and legacy cleanup.

  5. Account Deletion Data: Retention, Separation, and Recovery Design

    Design deleted-account data around verified retention rules, isolated storage, encryption, expiry, and the operational flows that may still need recovery.

  6. Discover Domain Concepts from Information and Behavior

    Use information and process or behavior from case-dependent viewpoints to distinguish transport events from domain concepts.

  7. Why Domain Concepts Should Not Mirror Database Tables

    Model business importance, hierarchy, and behavior instead of creating one domain object and repository for every persistence table.

  8. Improve a Bad Legacy Schema Behind a Code Boundary

    Hide cryptic tables behind repositories and meaningful types, regain control in code, then approach improvements to the legacy database.

  9. Design Distributed Tracing and Safe Production Logs Together

    Correlate requests across services while controlling log volume, masking sensitive fields, limiting access, and retaining only useful operational data.

  10. Why Pagination Count Queries Slow Down Databases

    Understand why exact totals can cost more than limited queries and when to consider slices, cached metadata, estimates, or product changes.

  11. Split Batch Ingestion from Processing to Reduce Retry Cost

    Stage external data, rerun internal transformations without repeating provider calls, and reduce the traffic and recovery costs of oversized batch jobs.

  12. Reduce Account-to-Profile Linkability in Anonymous Services

    Explore identifier separation, disposable mapping keys, minimal retention, and the recovery tradeoffs behind a privacy-oriented account model.

  13. Separate Core Data from Like-Count Aggregates

    Design scalable like-based ranking with separate aggregates, explicit freshness goals, async updates, reconciliation, and search boundaries that follow real demand.

  14. Use ID Range Gaps for Safer Database Rollbacks

    Separate legacy and new identifier ranges to prevent rollback collisions, simplify reverse migration, and make operational traffic easier to trace.

  15. Find Domain Boundaries Through Concept Lifecycles

    Compare creation, reads, changes, and deletion to judge cohesion, coupling, and boundaries among products, orders, payments, shipping, and settlement.

  16. Paginated Like Counts: Start with a Simple Query

    Count likes for the current page with a bounded query before adding counter columns or Redis and their added management costs.

  17. Protect Order Snapshots with Soft Delete and Boundaries

    Separate current products from immutable order snapshots, preserve refund history, and use status transitions or archives before destructive deletion.

  18. Keep Core Entities Light by Delaying ORM Associations

    Decide ORM associations by lifecycle and responsibility, separating searchable supporting data so core entities stay focused and adaptable.

  19. Keep Operational Tables Clean by Building a Separate Query Model

    Design operational tables around business concepts, then serve complex history and admin searches from a separate query model.

  20. Enums or Code Tables? Let the Rate of Change Decide

    Use enums for stable values and focused tables for frequently changing ones without turning one common-code table into a dumping ground.

  21. One Database, Separate Boundaries: Controlling Data Access by Domain

    How separate entity and repository boundaries can protect core rules from integration code even when both areas share one database table.

  22. Append, Don’t Overwrite: Designing Immutable Operational Data

    An append-only repayment example that makes history and synchronization clearer, along with the storage and query costs it introduces.

  23. Nullable or Zero? Choosing a Kotlin JPA Entity ID Strategy

    Compare nullable and zero-valued numeric IDs for Kotlin JPA entities, including new-entity detection, ambiguity, and verification.

  24. Track Database Changes with the Work That Ships Them

    Collect database changes with the issue and PR that need them, test them in development, and hand off the final release set before code deployment.

  25. Design for Change with Core Ownership and Surrogate Keys

    Centralize a shared registration rule in the core, escalate isolation only when needed, and keep changing business uniqueness out of the primary key.

  26. Rebuild First, Migrate Second

    Design a replacement system around the problems it must solve, then handle legacy data through explicit migration mappings and retirement conditions.

  27. Modeling Reactions from Requirements to Scale

    Turn a vague like-button request into a reaction model by clarifying policy, estimating data growth, and planning when count queries must change.

  28. Reversible Design Is the Antidote to Overengineering

    Build the requirement in front of you, look only a little beyond it, and keep speculative structures cheap to expand, remove, or replace.

  29. Foreign Keys Are an Operational Tradeoff, Not a Rule

    Choose foreign keys, indexes, and ORM mappings from integrity needs, incident response, deployment practice, and who operates the database.

  30. Reliable Database Tests Without a Shared Test Database

    Choose mocks, an in-memory database, Testcontainers, or a real database by the failure you need to catch, while keeping ordinary tests isolated from shared infrastructure.

  31. Choose Normalization from Requirements and Object Relationships

    Database normalization is not a score to maximize. Decide from change semantics, query cost, and the relationships the data is meant to preserve.