Rough Work/the craft

The Application is the Center

Traditional architecture diagrams show layers stacked like a cake. UI on top, business logic in the middle, database at the bottom. It looks stable.

┌─────────────────────────────┐
│            UI               │
│    (Presentation Layer)     │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│      Business Logic         │
│    (Application Layer)      │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│         Database            │
│       (Data Layer)          │
└─────────────────────────────┘

Changes ripple UP ↑

But that hierarchy makes the database foundational. Change the schema and the ripple travels up through the business logic into the UI. The infrastructure ends up driving the application.

What if you flip it? Put the application in the center. Let everything else plug in around it.

┌──────────┐  ┌──────────┐  ┌──────────┐
│  Web UI  │  │ REST API │  │   CLI    │
│ Adapter  │  │ Adapter  │  │ Adapter  │
└────┬─────┘  └─────┬────┘  └────┬─────┘
     │              │            │
     └──────────────┼────────────┘
                    │
          ┌─────────┴─────────┐
          │                   │
          │     APP CORE      │
          │   Domain Logic    │
          │                   │
          └─────────┬─────────┘
                    │
     ┌──────────────┼──────────────┐
     │              │              │
┌────┴─────┐  ┌─────┴────┐  ┌──────┴───┐
│ Database │  │  Email   │  │  Cache   │
│ Adapter  │  │ Adapter  │  │ Adapter  │
└──────────┘  └──────────┘  └──────────┘

Infrastructure plugs INTO the core

Now the application knows its domain—the rules and logic that make the software valuable. It doesn't know about HTTP. It doesn't know about SQL. It doesn't care where the data lives. The database is an adapter. The web server is an adapter. Third-party APIs are adapters. They connect to ports the application exposes:

// Port (defined by the application core)
interface UserRepository {
  save(user: User): Promise<void>;
}

// Adapter (defined by the infrastructure)
class PostgresUserRepository implements UserRepository {
  async save(user: User) {
    await db.query("INSERT INTO users...", [user]);
  }
}

This changes how you work. You can test business logic in total isolation—no slow database spin-up to verify a calculation. Swap PostgreSQL for an in-memory collection and the application doesn't blink.

The database isn't the foundation. It's just where you're storing data today. Build for the logic, and let the plumbing adapt.

to navigate