---
title: "Tesler's Law"
source: "/reference/teslers-law"
description: "Some complexity belongs to the problem itself; design determines where that complexity is handled and who must carry it."
---
# Tesler's Law

Some complexity belongs to the problem itself; design determines where that complexity is handled and who must carry it.



### Principle

Some complexity belongs to the problem itself; design determines where that complexity is handled and who must carry it.

### Why it matters

A system cannot always be made simpler by removing controls. Complexity can be absorbed by software through defaults, automation, validation, inference, and good information architecture, or pushed onto users through manual configuration and recall. Over-automation can also hide important decisions. Layr should ask whether complexity is allocated to the party best equipped to manage it.

### Deeper design interpretation

Some complexity cannot be removed because it belongs to the underlying problem. A migration may genuinely require mapping uncertain fields; permission systems may require policy decisions; financial workflows may require review. Design decides whether that complexity is handled by the user, by the system, or through a collaboration between both.

Good products absorb repetitive, mechanical, and deterministic complexity through defaults, derivation, validation, automation, and sensible inference. They keep consequential judgment visible to users. The challenge is avoiding two extremes: exposing every implementation detail as configuration, or hiding meaningful decisions behind opaque automation.

Layr should ask who is best equipped to handle each part of the complexity and what happens when the system is uncertain.

### What the agent should reason about

Classify complexity as mechanical, inferential, policy-based, or consequential. Mechanical complexity is often a strong automation candidate. Policy and high-consequence choices generally require explicit user involvement. Inferential automation should expose confidence and recovery when uncertainty is material.

The agent should evaluate total correction cost, not only initial setup effort. Automation that frequently guesses wrong may increase overall complexity.

### Common failure patterns

- Users manually transform data the system can derive exactly.
- High-confidence mappings require repetitive confirmation.
- The system makes financial or permission decisions silently.
- Advanced configuration is required for common cases with obvious defaults.
- Complexity is hidden until an error occurs, leaving no diagnosis path.

### Audit questions

- Which complexity is inherent to the task?
- Which part can the system handle deterministically?
- Where is human judgment necessary?
- How does the interface expose uncertainty and recovery when automation is imperfect?

### Example agent finding

> **High — Import mapping pushes deterministic work onto the user.** Twenty-three source columns exactly match destination fields by name and sample type, yet every mapping requires manual confirmation. Preselect high-confidence matches, show the evidence, and require explicit review only for ambiguous or consequential mappings.

### Agent directive

> Move avoidable mechanical complexity into the system while keeping consequential choices visible to the user.

### Apply this when

- Imports, configuration, data mapping, permissions, integrations, onboarding, scheduling, billing, and advanced workflows.

### Observable signals

- Users manually calculate or transform data the system already has.
- The interface exposes backend implementation constraints as user decisions.
- Automation makes a consequential choice without showing assumptions.
- Advanced configuration is mandatory for common cases with predictable defaults.
- The product hides necessary complexity until failure, leaving users unable to diagnose it.

### Recommended actions

- Automate repetitive transformation, validation, and sensible defaults.
- Surface uncertainty and assumptions when automation is imperfect.
- Require explicit input for decisions that involve policy, money, access, or irreversible consequences.
- Provide advanced controls after the common path, not before it.

### Do not over-apply

Automation is not automatically simpler. If the system cannot infer safely, explicit user control may reduce total complexity by preventing correction work.

### Example

**Weak:** An import asks users to manually map every obvious field even when names and sample values match with high confidence.

**Stronger:** High-confidence mappings are proposed and visible for review; ambiguous or consequential mappings require explicit confirmation.

### Evaluation notes

- **Default severity:** Medium to high in repeated or error-prone workflows.
- **Typical confidence:** High when the system already has the information needed to reduce manual work.
- **Primary evidence:** System capabilities, repeated input, automation confidence, decision consequence, error recovery.
- **Related rules:** Occam's Razor, Cognitive Load, Mental Model, Postel's Law

### References

- [Laws of UX — Tesler's Law](https://lawsofux.com/teslers-law/)
- [Laws of UX — Tesler's Law article](https://lawsofux.com/articles/2024/teslers-law/)

## Related rules

- [Occam's Razor](/__layr/pages/reference/occams-razor.md)
- [Cognitive Load](/__layr/pages/reference/cognitive-load.md)
- [Mental Model](/__layr/pages/reference/mental-model.md)
- [Postel's Law](/__layr/pages/reference/postels-law.md)

## Agent guidance

Review criteria, the finding contract a report must use, and worked examples.

Established principle; Layr interpretation and agent guidance. Category: Decision, Simplicity & Familiarity.

## Retrieve
- Canonical page: https://layr.design/reference/teslers-law
- Markdown for agents: https://layr.design/__layr/pages/reference/teslers-law.md
- Reference map: https://layr.design/llms.txt
- Route index: https://layr.design/__layr/routes.toon

## Rule object
```yaml
rule:
  id: "teslers-law"
  title: "Tesler's Law"
  category: "Decision, Simplicity & Familiarity"
  origin: established
  canonical_url: "https://layr.design/reference/teslers-law"
  principle: "Some complexity belongs to the problem itself; design determines where that complexity is handled and who must carry it."
  directive: "Move avoidable mechanical complexity into the system while keeping consequential choices visible to the user."
  applies_when:
    - "Imports, configuration, data mapping, permissions, integrations, onboarding, scheduling, billing, and advanced workflows."
  observable_signals:
    - "Users manually calculate or transform data the system already has."
    - "The interface exposes backend implementation constraints as user decisions."
    - "Automation makes a consequential choice without showing assumptions."
    - "Advanced configuration is mandatory for common cases with predictable defaults."
    - "The product hides necessary complexity until failure, leaving users unable to diagnose it."
  audit_questions:
    - "Which complexity is inherent to the task?"
    - "Which part can the system handle deterministically?"
    - "Where is human judgment necessary?"
    - "How does the interface expose uncertainty and recovery when automation is imperfect?"
  recommended_actions:
    - "Automate repetitive transformation, validation, and sensible defaults."
    - "Surface uncertainty and assumptions when automation is imperfect."
    - "Require explicit input for decisions that involve policy, money, access, or irreversible consequences."
    - "Provide advanced controls after the common path, not before it."
  avoid_when:
    - "Automation is not automatically simpler. If the system cannot infer safely, explicit user control may reduce total complexity by preventing correction work."
  common_failure_patterns:
    - "Users manually transform data the system can derive exactly."
    - "High-confidence mappings require repetitive confirmation."
    - "The system makes financial or permission decisions silently."
    - "Advanced configuration is required for common cases with obvious defaults."
    - "Complexity is hidden until an error occurs, leaving no diagnosis path."
  evidence_types:
    - "System capabilities"
    - "repeated input"
    - "automation confidence"
    - "decision consequence"
    - "error recovery"
  default_severity: "Medium to high in repeated or error-prone workflows."
  typical_confidence: "High when the system already has the information needed to reduce manual work."
  related_rules:
    - { id: "occams-razor", title: "Occam's Razor", url: "https://layr.design/reference/occams-razor" }
    - { id: "cognitive-load", title: "Cognitive Load", url: "https://layr.design/reference/cognitive-load" }
    - { id: "mental-model", title: "Mental Model", url: "https://layr.design/reference/mental-model" }
    - { id: "postels-law", title: "Postel's Law", url: "https://layr.design/reference/postels-law" }
```

## What to reason about
Classify complexity as mechanical, inferential, policy-based, or consequential. Mechanical complexity is often a strong automation candidate. Policy and high-consequence choices generally require explicit user involvement. Inferential automation should expose confidence and recovery when uncertainty is material. The agent should evaluate total correction cost, not only initial setup effort. Automation that frequently guesses wrong may increase overall complexity.

## Routing
Route a review here when the user must choose between alternatives, learn an unfamiliar control, navigate competing actions, or configure a system before reaching value. Inspect the structure of the decision before recommending fewer options.

## Review procedure
For every finding:
1. Identify the exact component, state, route, or interaction.
2. State the observable evidence.
3. Name the principle that applies.
4. Explain the user consequence in the current context.
5. Estimate severity from the consequence, frequency, and reversibility.
6. Recommend the smallest change that addresses the issue while preserving the product's existing design system.
7. Lower confidence when intent, frequency, audience, device, or product constraints must be inferred.
8. Do not produce generic advice such as "improve hierarchy" or "make this clearer" without specifying what is wrong and why.

## Finding contract — emit exactly this shape
```yaml
finding:
  rule_id: string
  location: string
  evidence:
    - observable fact
  impact: string
  severity: low | medium | high | critical
  confidence: low | medium | high
  recommendation:
    change: string
    rationale: string
    preserve:
      - existing design-system behavior
      - valid product constraints
```

## Example finding for this rule
High — Import mapping pushes deterministic work onto the user. Twenty-three source columns exactly match destination fields by name and sample type, yet every mapping requires manual confirmation. Preselect high-confidence matches, show the evidence, and require explicit review only for ambiguous or consequential mappings.

## Code reference

The same principle as markup. Compare the structure, not the class names.

```html
<!-- weak -->
<div class="example-ui example-ui-weak">
  <div class="scene-chrome">
    <span class="scene-chrome-app">Import</span>
    <span class="scene-chrome-view">Field mapping</span>
  </div>
  <div class="scene-body">
    <div class="scene-panel">
      <span class="scene-panel-title">Map 4 fields</span>
      <div class="scene-map-row">
        <span class="scene-key">email</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-neutral">Choose field ⌄</span>
      </div>
      <div class="scene-map-row">
        <span class="scene-key">created_at</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-neutral">Choose field ⌄</span>
      </div>
      <div class="scene-map-row">
        <span class="scene-key">full_name</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-neutral">Choose field ⌄</span>
      </div>
      <div class="scene-map-row scene-map-row-flagged">
        <span class="scene-key">status_code</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-neutral">Choose field ⌄</span>
      </div>
      <span class="scene-action scene-action-primary">Continue</span>
      <span class="scene-note">4 of 4 mappings entered by hand</span>
    </div>
  </div>
</div>
```

```html
<!-- stronger -->
<div class="example-ui example-ui-strong">
  <div class="scene-chrome">
    <span class="scene-chrome-app">Import</span>
    <span class="scene-chrome-view">Field mapping</span>
  </div>
  <div class="scene-body">
    <div class="scene-panel">
      <span class="scene-panel-title">Map 4 fields</span>
      <div class="scene-map-row">
        <span class="scene-key">email</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-accent">Email</span>
        <span class="scene-meter">
          <span class="scene-meter-fill" style="width:99%"></span>
        </span>
        <span class="scene-meta">99%</span>
      </div>
      <div class="scene-map-row">
        <span class="scene-key">created_at</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-accent">Created date</span>
        <span class="scene-meter">
          <span class="scene-meter-fill" style="width:98%"></span>
        </span>
        <span class="scene-meta">98%</span>
      </div>
      <div class="scene-map-row">
        <span class="scene-key">full_name</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-accent">Name</span>
        <span class="scene-meter">
          <span class="scene-meter-fill" style="width:96%"></span>
        </span>
        <span class="scene-meta">96%</span>
      </div>
      <div class="scene-map-row scene-map-row-flagged">
        <span class="scene-key">status_code</span>
        <span class="scene-map-arrow" aria-hidden="true">→</span>
        <span class="scene-tag scene-tag-warning">Confirm</span>
        <span class="scene-meta">Status or Stage?</span>
      </div>
      <div class="scene-row">
        <span class="scene-action scene-action-primary">Accept 3 proposals</span>
        <span class="scene-action">Resolve 1 flagged</span>
      </div>
      <span class="scene-note">Assumptions visible · one real decision left to the user</span>
    </div>
  </div>
</div>
```

```css
/* declarations these studies depend on */
.example-ui { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; min-height: 17rem; overflow: hidden; border: var(--border-thin) solid var(--color-border-strong); background: var(--color-background); color: var(--color-text); font-size: var(--text-xs); line-height: var(--leading-snug); }
.example-ui .scene-chrome { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: var(--border-thin) solid var(--color-border-strong); background: var(--color-surface); }
.example-ui .scene-chrome-app { font-size: var(--text-2xs); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.example-ui .scene-chrome-view { color: var(--color-text-tertiary); font-size: var(--text-2xs); }
.example-ui .scene-body { display: grid; align-content: start; gap: var(--space-3); min-width: 0; padding: var(--space-3); }
.example-ui .scene-body:has(> .scene-panel:only-child) { align-content: stretch; }
.example-ui .scene-panel { display: grid; align-content: start; justify-items: start; gap: var(--space-2); min-width: 0; padding: var(--space-3); border: var(--border-thin) solid var(--color-border-strong); background: var(--color-surface-raised); }
.example-ui .scene-panel-title { font-size: var(--text-sm); font-weight: 600; letter-spacing: var(--tracking-heading); }
.example-ui .scene-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: var(--space-1) var(--space-2); width: 100%; min-width: 0; padding-block: var(--space-1); }
.example-ui .scene-panel > .scene-row + .scene-row { border-top: var(--border-thin) solid var(--color-border-subtle); }
.example-ui .scene-meta { color: var(--color-text-tertiary); font-size: var(--text-2xs); }
.example-ui .scene-key { font-family: var(--font-mono); font-size: var(--text-2xs); }
.example-ui .scene-note { width: 100%; padding-top: var(--space-2); border-top: var(--border-thin) solid var(--color-border-subtle); color: var(--color-text-tertiary); font-family: var(--font-mono); font-size: var(--text-2xs); line-height: var(--leading-snug); }
.example-ui .scene-action { display: inline-flex; align-items: center; justify-content: center; min-height: var(--space-8); padding-inline: var(--space-3); border: var(--border-thin) solid var(--color-border-strong); border-radius: var(--radius-xs); background: var(--color-surface-raised); color: var(--color-text); font-size: var(--text-xs); font-weight: 550; white-space: nowrap; }
.example-ui .scene-action-primary { border-color: var(--color-primary-bg); background: var(--color-primary-bg); color: var(--color-primary-text); }
.example-ui .scene-tag { display: inline-block; padding: 0 var(--space-2); border: var(--border-thin) solid var(--color-border-strong); color: var(--color-text-secondary); font-size: var(--text-2xs); line-height: 1.6; white-space: nowrap; }
.example-ui .scene-tag-neutral { border-color: var(--color-border-strong); }
.example-ui .scene-tag-accent { border-color: var(--color-action); color: var(--color-accent-text); }
.example-ui .scene-tag-warning { border-color: var(--color-caution); color: var(--color-caution); }
.example-ui .scene-meter { display: block; width: var(--space-10); height: var(--space-1); background: var(--color-border-subtle); }
.example-ui .scene-meter-fill { display: block; height: 100%; background: var(--color-action); }
.example-ui .scene-map-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); width: 100%; padding-block: var(--space-2); border-top: var(--border-thin) solid var(--color-border-subtle); }
.example-ui .scene-map-row-flagged { border-left: 2px solid var(--color-caution); padding-left: var(--space-2); }
.example-ui .scene-map-arrow { color: var(--color-text-tertiary); }
.example-ui { min-height: 15rem; }

/* resolved values */
:root {
  --border-thin: 1px;
  --font-mono: "Geist Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  --leading-snug: 1.35;
  --radius-xs: 2px;
  --space-1: 0.25rem;
  --space-10: 2.5rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-8: 2rem;
  --text-2xs: 0.6875rem;
  --text-sm: 0.875rem;
  --text-xs: 0.75rem;
  --tracking-heading: -0.025em;
  --tracking-label: 0.06em;
}
```

## Weak vs stronger
- Weak: An import asks users to manually map every obvious field even when names and sample values match with high confidence.
- Stronger: High-confidence mappings are proposed and visible for review; ambiguous or consequential mappings require explicit confirmation.

## Reporting rules
- Report only what the interface shows as observable evidence; phrase psychological or motivational effects as possible consequences.
- Returning no finding is a valid result when evidence is insufficient.
