1. Before Fixing Circular Dependencies, Fix the Domain Model

    Resolve confusing ownership and concept boundaries before using interfaces or dependency inversion to treat an apparent circular reference.

  2. 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.

  3. One Project, Many Deployables: Drawing Boundaries by Runtime Role

    Separate public, admin, batch, and operations workloads into runnable applications without splitting the whole codebase into separate projects too early.

  4. Name Readers, Finders, and Searchers by Behavior

    Distinguish Reader, Finder, and Searcher classes by direct reads, added filtering, and composite searches rather than result count.

  5. Compose My Page Data Without Inventing a My Domain

    Build My page summaries through a dedicated composition layer while keeping user, order, and product responsibilities in their proper domains.

  6. Why a My Page Is Not a Domain

    A My Page is a client-facing view, not a business domain. Keep orders, products, and coupons with their real owners and combine them at the boundary.

  7. Designing Domain Models Beyond the Shape of the UI

    A tree-shaped API does not require a tree-shaped domain. Keep the client contract at the presentation boundary and compose it from internal concepts.

  8. Your First Test Can Be Messy—Refactor It Later

    Start with the test that proves the behavior you care about, mock enough to make it run, and improve test design through repeated use and review.

  9. Keep API Request Models Out of the Core Domain

    Convert external request objects into business-owned values at the presentation boundary so the API depends inward and the core never depends back.

  10. 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.

  11. Give Cross-Domain Behavior to the Domain That Owns It

    Before placing a caller-owned interface across modules, identify which domain owns the action and let callers depend on that capability.

  12. Who Owns the Enum? Dependency Design Across Domain Modules

    Put a business enum with its domain, let storage depend inward, and use a small shared enum module only while the domain boundary is still emerging.

  13. Provider Identity and Authentication Boundaries for Platform APIs

    How a small platform API resolves provider keys into a domain identity, separates tenant data, and chooses an authentication boundary that fits its scale.

  14. Domain Models First: A Conservative Approach to JPA Associations

    A cautious way to map JPA entities: start with IDs, add associations only when lifecycles truly align, and model business concepts independently.

  15. You Can Practice High-Traffic Engineering Without Real Traffic

    Build and operate a small service, create load deliberately, and show how you found and fixed bottlenecks without pretending a load test equals production experience.

  16. 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.

  17. Do Not Create a DTO for Every Layer by Habit

    Use DTOs where data crosses a boundary with a different contract. Mapping has a cost, but so does letting external request shapes define the inside of a service.

  18. Put Circuit Breakers Next to the Failing I/O

    Circuit breakers, timeouts, cache fallbacks, and remote-call policies belong near the implementation that performs the I/O, while domain code chooses the required behavior.

  19. Timeouts Are Product Decisions, Not Just Client Settings

    Design timeout, retry, and recovery policies from the user's waiting budget and the uncertainty of each failure instead of applying one retry rule everywhere.

  20. Do Not Split Modules Before the Domain Has Matured

    Domain maturity comes from understanding policy, behavior, and operating reality. Let those lessons reveal module boundaries instead of freezing guesses too early.

  21. Upgrade Dependencies Before the Gap Becomes a Project

    Frequent, prioritized dependency upgrades keep change small, expose compatibility problems early, and prevent a maintained service from quietly accumulating debt.

  22. When an AI Agent Calls the Same Tool Twice

    Retries are normal in distributed systems and AI workflows. Use database constraints, idempotency keys, and bounded retries to prevent duplicate side effects.

  23. Gradle Dependency Scopes Are Architectural Boundaries

    Use Gradle implementation, api, runtimeOnly, and compileOnly deliberately to express module access, prevent accidental coupling, and preserve design intent.

  24. Isolate Admin Work from the Service Domain

    Admin APIs have different queries, mutation needs, and release risks. Isolate them by module or repository instead of letting operational convenience reshape the core service.

  25. Use Reader and Writer Components to Reveal Business Flow

    Reader and writer components can hide storage details, narrow change, and let the business layer show policy, but only when the software's lifetime justifies them.

  26. Carry One Trace ID across Distributed Services

    Logs become operationally useful when one request can be followed across HTTP calls and asynchronous events without exposing sensitive data or flooding storage.

  27. Reuse Below the Use-Case Layer

    When use cases call one another for reuse, business changes spread and cycles follow. Compose above them or extract focused implementation components below them.

  28. How to Split a Large Service Class by Responsibility and Layer

    Use constructor dependencies and imports to diagnose an oversized service, then separate cohesive responsibilities before adding another architecture label.

  29. 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.