Skip to content

OTP Thinking for Elixir

Introduction

OTP Thinking is a specialized skill for Claude Code designed to guide developers through the nuances of the Erlang/Elixir Open Telecom Platform (OTP). While many developers are familiar with basic syntax, mastering concurrency, fault tolerance, and state management requires a paradigm shift.

This skill helps you navigate complex architectural decisions, such as when to use a GenServer versus a simple Task, or choosing between Oban and Broadway for background processing. By integrating this skill, Claude becomes an expert architect capable of auditing your supervision trees and identifying potential throughput bottlenecks before they reach production.

Key Features:

  • Architectural Guardrails: Prevents common anti-patterns like wrapping stateless functions in GenServer.
  • Concurrency Logic: Expert advice on Task.Supervisor usage and async_nolink patterns.
  • Process Management: Guidance on DynamicSupervisor, Registry, and PartitionSupervisor for scaling to millions of processes.
  • Job Processing: Clear decision frameworks for choosing between Oban (persistence) and Broadway (ingestion).
  • Debugging & Observability: Quick access to :sys tracing and Telemetry integration patterns.

Installation

To add the OTP Thinking skill to your Claude Code environment, ensure you have the claude-code-elixir repository cloned or the specific skill file available in your configuration path.

  1. Clone the repository:

    Terminal window
    git clone https://github.com/georgeguimaraes/claude-code-elixir.git
  2. Add to Claude Code: Copy the otp-thinking skill definition into your Claude Code skills directory (typically .claudecode/skills/ or as defined in your local setup).

  3. Verify: Ask Claude: “What are the rules for using GenServers?” to trigger the skill logic.

Usage

This skill is automatically triggered when you discuss Elixir concurrency, background jobs, or system design. You can also explicitly invoke its logic with specific prompts:

Example Prompts:

  • “I need to cache this data in memory. Should I use a GenServer or ETS?”
  • “How do I handle concurrent requests without creating a bottleneck?”
  • “Review my supervision tree: I’m using :one_for_all but I’m worried about restart loops.”
  • “Should I use Oban or Broadway for processing SQS messages?”

The Iron Law of OTP

GENSERVER IS A BOTTLENECK BY DESIGN

A GenServer processes exactly one message at a time. This skill enforces a “read-bypass” pattern: use GenServer for serialized writes and ETS with :read_concurrency for high-throughput reads.

Abstraction Decision Tree

When you ask Claude how to structure a feature, it uses the following logic provided by this skill:

  • Need State?
    • No → Use a Plain Function.
    • Yes → Is it complex behavior?
      • No → Use an Agent.
      • Yes → Need Supervision?
        • No → Use spawn_link.
        • Yes → Is it Request/Response?
          • No → Use Task.Supervisor.
          • Yes → Explicit States?
            • No → GenServer.
            • Yes → GenStateMachine.

Storage & Persistence

The skill provides instant documentation for Elixir storage options:

NeedRecommended Tool
Memory CacheETS (fast reads/writes)
Static Config:persistent_term (optimized for reads)
Disk PersistenceDETS (simple, 2GB limit)
Distributed TransactionsMnesia

Debugging Tips

If your system is behaving unexpectedly, you can ask Claude to provide :sys debugging commands:

:sys.get_state(pid) # Inspect current state
:sys.trace(pid, true) # Trace process events

Note: Always remember to turn off tracing when finished to avoid performance degradation.