Engineering Atlas › Low-Level Design

Drawing UML use case diagrams

12 min read · last reviewed 2026-10-17

Open in the interactive app: practice, quiz, mock interview →

In one minute

How it works

The four elements

A telehealth clinic is building a booking platform. Its use case diagram has four kinds of things.

The system boundary is a rectangle named for the system ("Clinic Platform"). Inside is what the team builds; outside is what it talks to. Drawing it forces the first scope argument: is payments inside, or is the payment provider an actor?

Actors stand outside the boundary: stick figures for humans, boxes marked <<system>> for machines. The clinic has Patient, Clinician, Front Desk and Billing Admin, plus the Insurer's eligibility service as a secondary actor that the system calls but that never starts anything.

Use cases are ovals inside the boundary, each a verb phrase for a goal the actor would recognise: Book appointment, Write prescription. "Save row" is not a use case; nobody opens the app wanting to save a row. Associations are plain lines joining an actor to its use cases.

Include, extend and generalization

Three relationships connect elements to each other, and they are the part most teams get wrong.

<<include>> is a dashed arrow from the base to the included use case. Book appointment includes Verify insurance: every booking verifies. Inclusion factors out shared behaviour the way a function does, and Verify insurance needs no actor of its own.

<<extend>> is a dashed arrow from the optional extension to the base, the opposite direction. Apply late fee extends Cancel appointment at an extension point called "within 24 hours of the visit". The base is complete without the extension and does not know it exists, which is the open-closed principle drawn as a picture.

Generalization (solid line, hollow triangle) works on actors and use cases. Billing Admin specializes Front Desk: it can do everything Front Desk can, plus issue refunds. Specialized actors inherit their parent's associations, the same way a subclass inherits methods.

A good rule for spotting misuse: if you would describe the relationship with "sometimes" or "if", it is extend; with "always", it is include; with "first X, then Y", it does not belong on this diagram at all. Sequencing goes on an activity or sequence diagram.

The text behind each oval

Every oval should point at a short written specification: goal, primary actor, preconditions, the main success scenario as numbered steps, extensions (what happens when step 3 fails), and postconditions, as in Alistair Cockburn's template. The diagram is the index and the text is the content; teams that keep only the diagram lose the failure cases, where most design work lives.

Drawing it in Mermaid

Mermaid has no use case diagram type, so a flowchart stands in: a subgraph for the boundary, stadium nodes (["..."]) for use cases, and labelled dotted edges for include and extend. PlantUML supports the notation directly with actor, usecase and rectangle.

Reviewing agent-written diagrams

Agents make the human mistakes faster: CRUD ovals that mirror tables, extend arrows pointing the wrong way, and actors from the org chart ("Manager") that match no role in the identity provider. Ask for the matrix the diagram implies (actor, use case, endpoint, permission) and check it against the code, which the practice task automates.

The same shape elsewhere

A use case diagram is a coverage claim, the trust but verify shape. An auditor mapping controls to evidence and a gateway route table compared with the OpenAPI spec are the same check: two lists written by different people must agree, and gaps in either direction are the findings.

Down the stack

Layer 1The contract

The diagram makes three testable promises. A principal holding an associated actor's role can complete the use case end to end, inclusions included. Included use cases run whenever the base does, so the base actor needs whatever they need. And an actor with no line to a use case cannot perform it; that negative promise is the one auditors test. Nothing is promised about ordering, timing or data.

Layer 2The mechanism

Actors become principals and roles: a scope or roles claim in an OAuth 2.0 JWT, a Kubernetes Role and RoleBinding, an AWS IAM role. Actor generalization becomes role inheritance.

Use cases become entry points: REST routes, gRPC methods, GraphQL mutations or queue consumers. Mature teams record the link, for example with an OpenAPI x-use-case extension, so tooling can join the two.

Include becomes an internal call on the same request path, and its permission propagates up: if POST /appointments calls the eligibility service with the caller's token, that token needs the eligibility scope. Extend becomes a conditional hook (a feature flag, a policy rule, a handler for AppointmentCancelled) the base never references. The boundary becomes the authorization perimeter, usually a gateway or mesh.

Tooling does the drawing. PlantUML parses its text into an element graph and hands use case and class diagrams to Graphviz's dot. Mermaid parses flowchart text with a Jison-generated grammar into a graph of nodes, edges and subgraphs, then lays it out with dagre by default (ELK is an option). Both layout engines use the layered method from Sugiyama and colleagues: break cycles, assign each node a rank, order nodes within ranks to reduce edge crossings, then assign coordinates.

Layer 3The machine

Each association costs something on every request. A scope check on a validated JWT is a set lookup costing well under a microsecond, but validating the token costs more: an RS256 signature check is roughly tens of microseconds on a modern core, which is why gateways cache validated tokens by hash. Scope strings ride in a header on every call. A role model with one scope per use case and 60 use cases adds over a kilobyte to the token, base64 adds a third more, and nginx's default large_client_header_buffers 4 8k rejects any single header line above 8 KB with a 400. Calling an external policy engine such as OPA over the network adds a millisecond or so per decision; embedding it keeps decisions in the tens of microseconds.

Layout has its own limit. Minimising edge crossings in a layered drawing is NP-hard, so engines sweep barycenter or median heuristics. With a few hundred edges the result becomes unreadable long before it becomes slow: split the diagram by actor or subsystem.

Why it's built this way

  1. Stakeholders argue about scope and access long before anyone argues about classes, so the first diagram models goals and roles, not structure.
  2. Roles change less often than people, so actors are roles, and they map directly onto the role or scope model enforced at runtime.
  3. Shared behaviour would otherwise be repeated in every use case text, so include factors it out, and its permissions propagate to every caller.
  4. Optional behaviour added later should not force edits to the base, so extend points from the extension to the base.
  5. Hand-maintained lists drift, so the diagram, the route table and the role grants are joined into one checked matrix.

Diagram

flowchart LR
  P["Patient"]
  F["Front Desk"]
  B["Billing Admin"]
  C["Clinician"]
  I["Insurer (system)"]
  subgraph S["Clinic Platform"]
    U1(["Book appointment"])
    U2(["Verify insurance"])
    U3(["Cancel appointment"])
    U4(["Apply late fee"])
    U5(["Write prescription"])
    U6(["Issue refund"])
  end
  P --- U1
  P --- U3
  F --- U1
  F --- U3
  B -- "specializes" --> F
  B --- U6
  C --- U5
  U1 -. "include" .-> U2
  U4 -. "extend" .-> U3
  U2 --- I

Worked example

The clinic's first release has 9 use cases, 14 endpoints and 5 roles. For the security review an engineer joins three files: the use case list, the OpenAPI spec (each operation tagged with x-use-case and a scope), and the identity provider's role export. The join finds four problems:

  1. GET /appointments/export, added for a one-off migration, has no use case and returns every patient's appointments to any appt:read token. It is deleted.
  2. Patient lacks insurance:check. The booking service forwards the caller's token to the eligibility service, so every patient booking would fail with a 403. Integration tests used an admin token and missed it.
  3. Front Desk holds rx:write, granted during testing. No front desk use case needs it, and prescription write access for non-clinicians is a reportable audit finding.
  4. Reschedule appointment has no endpoint: design assumed cancel-and-rebook, product assumed a dedicated flow. Settled in 20 minutes, before launch.

At 14 endpoints this is a spreadsheet. A year later, at 120 endpoints and 30 roles, the same check runs in CI on every change to the spec or the roles.

Trade-offs

OptionStrengthsWeaknessesChoose when
Use case diagram plus written scenariosScope, roles and failure cases agreed earlyTwo artefacts to keep in stepNew product areas, regulated domains
User stories onlySmall, fits sprint planningNo single view of who can do whatSmall teams, low access-control risk
Diagram generated from route and role metadataAlways matches the codeShows what exists, not what was intendedLarge APIs, audits
Access matrix table, no diagramEasy to diff and check in CIHard to read for non-engineersMature systems with many roles

Pitfalls in production

Leadership lens

Check yourself

  1. Booking always checks insurance; cancelling sometimes charges a fee. Which is include and which is extend, and which way does each arrow point?

    Show answer

    Insurance is include, pointing from Book to Verify insurance. The fee is extend, pointing from Apply late fee to Cancel, because the base must not depend on the optional behaviour.

  2. Why does an actor need the permissions of use cases it never directly invokes?

    Show answer

    Included use cases run as part of the base, often with the caller's credentials, so their requirements propagate to every actor of the base.

  3. Billing Admin specializes Front Desk. What does that mean for access?

    Show answer

    Billing Admin inherits every Front Desk association and grant and adds its own; in RBAC terms its role inherits the Front Desk role.

  4. What does a missing line between an actor and a use case promise?

    Show answer

    That the role cannot perform it. That negative claim is what least-privilege checks and audits test.

Watch

Free resources

Open in the interactive app: practice, quiz, mock interview →