Flowchart Symbols and How to Use Them

A practical guide to flowchart symbols with real examples using Mermaid diagrams

I’ve drawn many flowcharts over my career. A well-drawn flowchart can explain a complicated workflow in seconds. But you need to know the right symbols.

Here’s a practical guide to flowchart symbols and how to actually use them.

Why Flowcharts Matter

Before we get into symbols, here’s why flowcharts are still relevant:

They force clarity. If you can’t draw a flowchart of your process, you don’t fully understand it.

They reveal problems. Dead ends, infinite loops, missing error handling - all obvious in a flowchart.

They communicate fast. A flowchart shows the flow in a way that paragraphs of text never will.

I’ve used flowcharts to:

  • Understand operating system flows and dig deeper into how things work
  • Debug production incidents
  • Explain algorithms (especially recursive ones)

The Essential Symbols

1. Terminal / Terminator

Shape: Rounded rectangle (oval) Purpose: Start and end points of your flow

graph TD Start([Start]) --> End([End])

Use clear labels: “Start”, “Begin”, “End”, “Exit”. This tells readers where the flow begins and where it terminates.

2. Process / Rectangle

Shape: Rectangle Purpose: An action, operation, or process step

graph TD Start([Start]) Start --> Process1[Read configuration file] Process1 --> Process2[Parse JSON] Process2 --> Process3[Initialize database] Process3 --> End([End])

This is your workhorse symbol. Use verbs: “Calculate total”, “Send email”, “Save to database”.

3. Decision / Conditional

Shape: Diamond Purpose: A question with Yes/No or True/False outcomes

graph TD Start([Start]) Start --> Check{File exists?} Check -->|Yes| Read[Read file] Check -->|No| Error[Show error] Read --> End([End]) Error --> End

Always label the arrows coming out. “Yes/No”, “True/False”, or specific conditions like “>100” and “≤100”.

4. Data (I/O)

Shape: Parallelogram Purpose: Input or output of data

graph TD Start([Start]) Start --> Input[/Enter username and password/] Input --> Validate{Valid credentials?} Validate -->|Yes| Output[/Display dashboard/] Validate -->|No| Error[/Show error message/] Output --> End([End]) Error --> End

Use this for user input, file reads, API responses, or any data coming in or going out.

5. Document

Shape: Rectangle with wavy bottom Purpose: A document or report generated

In Mermaid, we approximate this with special notation:

graph TD Start([Start]) Start --> Process[Generate monthly report] Process --> Doc[/Report PDF/] Doc --> Email[Email to stakeholders] Email --> End([End])

Use this when your process creates or reads a specific document.

6. Subroutine / Predefined Process

Shape: Rectangle with double vertical lines Purpose: A process defined elsewhere (function call, subprocess)

graph TD Start([Start]) Start --> Input[/Get user input/] Input --> Validate[[Validate input]] Validate --> Process[Process data] Process --> Save[[Save to database]] Save --> End([End])

The double brackets [[...]] in Mermaid create this style. Use it for reusable processes or functions that are detailed in separate flowcharts.

Real-World Examples

Example 1: User Login Flow

graph TD Start([User visits login page]) Start --> Input[/Enter email and password/] Input --> Submit[Click login button] Submit --> Validate{Credentials valid?} Validate -->|No| Error[/Display error message/] Error --> Input Validate -->|Yes| Check{2FA enabled?} Check -->|No| Dashboard[/Redirect to dashboard/] Check -->|Yes| TwoFactor[/Prompt for 2FA code/] TwoFactor --> EnterCode[/Enter 2FA code/] EnterCode --> VerifyCode{Code valid?} VerifyCode -->|No| Error2[/Show error/] Error2 --> TwoFactor VerifyCode -->|Yes| Dashboard Dashboard --> End([End])

This shows a complete authentication flow with error handling and conditional 2FA.

Example 2: Deployment Process

graph TD Start([Start deployment]) Start --> Tests[[Run test suite]] Tests --> TestPass{Tests passed?} TestPass -->|No| Notify[/Notify team/] Notify --> End([Deployment failed]) TestPass -->|Yes| Build[Build Docker image] Build --> Push[Push to registry] Push --> Deploy[Deploy to staging] Deploy --> Smoke{Smoke tests passed?} Smoke -->|No| Rollback[Rollback deployment] Rollback --> Notify Smoke -->|Yes| Prod{Deploy to production?} Prod -->|No| End2([End]) Prod -->|Yes| ProdDeploy[Deploy to production] ProdDeploy --> Monitor[Monitor metrics] Monitor --> Success([Deployment complete])

This shows a typical CI/CD pipeline with testing gates and rollback logic.

Example 3: E-commerce Checkout

graph TD Start([User clicks checkout]) Start --> Cart{Cart empty?} Cart -->|Yes| Error[/Show error message/] Error --> End([Return to shop]) Cart -->|No| Address[/Enter shipping address/] Address --> Payment[/Enter payment info/] Payment --> Validate[[Validate payment]] Validate --> Valid{Payment valid?} Valid -->|No| Retry{Retry?} Retry -->|Yes| Payment Retry -->|No| Cancel([Order cancelled]) Valid -->|Yes| Process[Process order] Process --> Inventory{Items in stock?} Inventory -->|No| Backorder[Create backorder] Inventory -->|Yes| Ship[Create shipping label] Backorder --> Notify[/Email customer/] Ship --> Confirm[/Send confirmation email/] Confirm --> Success([Order complete]) Notify --> Success

This shows decision points, error handling, and multiple end states.

Example 4: API Request Handler

graph TD Start([Receive API request]) Start --> Auth{Valid auth token?} Auth -->|No| Unauth[/Return 401 Unauthorized/] Unauth --> End([End]) Auth -->|Yes| Validate[[Validate request body]] Validate --> Valid{Schema valid?} Valid -->|No| BadReq[/Return 400 Bad Request/] BadReq --> End Valid -->|Yes| Check{Resource exists?} Check -->|No| NotFound[/Return 404 Not Found/] NotFound --> End Check -->|Yes| Process[Process request] Process --> Error{Error occurred?} Error -->|Yes| ServerErr[/Return 500 Server Error/] ServerErr --> End Error -->|No| Success[/Return 200 with data/] Success --> End

This shows how to document API logic with proper HTTP status codes.

Example 5: Recursive Function

graph TD Start([calculateFactorial n]) Start --> Base{n == 0 or n == 1?} Base -->|Yes| Return1[Return 1] Return1 --> End([End]) Base -->|No| Recurse[[calculateFactorial n-1]] Recurse --> Multiply[Multiply result by n] Multiply --> Return2[Return result] Return2 --> End

Recursion is easier to understand with a flowchart. The [[...]] notation shows the recursive call.

Tips for Drawing Better Flowcharts

1. Keep It Simple

Don’t try to fit your entire system into one flowchart. Break complex flows into multiple diagrams.

Bad: One massive flowchart with 50 boxes Good: Main flowchart with subroutines, each detailed separately

2. Use Consistent Spacing

Align your boxes. Keep arrows clean. Messy flowcharts are hard to read.

3. Label Everything

Every decision diamond needs labels on its outputs. Every process box needs a clear action.

Bad: Diamond with “Check” and arrows with no labels Good: Diamond with “User age >= 18?” and arrows labeled “Yes” and “No”

4. Show Error Paths

Don’t just show the happy path. Show what happens when things fail.

graph TD Start([Start]) Start --> API[Call external API] API --> Success{API success?} Success -->|Yes| Process[Process response] Success -->|No| Retry{Retry < 3?} Retry -->|Yes| Wait[Wait 1 second] Wait --> API Retry -->|No| Error[/Log error and alert/] Process --> End([End]) Error --> End

This shows retry logic and error handling - critical for production systems.

5. Avoid Spaghetti

If your flowchart has arrows going everywhere, it’s too complex. Simplify your logic or break it into sub-processes.

6. Use Color Sparingly

In Mermaid, you can add color for emphasis:

graph TD Start([Start]) Start --> Process[Normal process] Process --> Critical[Critical security check] Critical --> End([End]) style Critical fill:#ff6b6b,stroke:#c92a2a,color:#fff

But don’t overdo it. Color should highlight important nodes, not decorate everything.

Common Flowchart Patterns

The Retry Loop

graph TD Start([Start]) Start --> Try[Attempt operation] Try --> Success{Success?} Success -->|Yes| Done([End]) Success -->|No| Count{Retry count < max?} Count -->|Yes| Inc[Increment retry count] Inc --> Try Count -->|No| Fail([Give up])

Use this pattern for network calls, database operations, or any unreliable external dependency.

The Validation Chain

graph TD Start([Start]) Start --> V1{Check 1 valid?} V1 -->|No| E1[/Error: Check 1 failed/] E1 --> End([End]) V1 -->|Yes| V2{Check 2 valid?} V2 -->|No| E2[/Error: Check 2 failed/] E2 --> End V2 -->|Yes| V3{Check 3 valid?} V3 -->|No| E3[/Error: Check 3 failed/] E3 --> End V3 -->|Yes| Success[Process data] Success --> End

Use this when you have multiple validation checks that must all pass.

The Batch Processor

graph TD Start([Start]) Start --> Get[Get next item] Get --> More{Items remaining?} More -->|No| Done([End]) More -->|Yes| Process[Process item] Process --> Error{Error?} Error -->|Yes| Log[Log error] Error -->|No| Get Log --> Get

Use this for processing queues, files, or any batch operation.

Creating Flowcharts with Mermaid

All the diagrams in this article are written in Mermaid syntax. Here’s a quick reference:

graph TD A([Start]) --> B[Process] B --> C{Decision?} C -->|Yes| D[/Output/] C -->|No| E[[Subroutine]] D --> F([End]) E --> F

Syntax:

  • graph TD - Top to bottom flow (use LR for left to right)
  • ([...]) - Rounded rectangle (terminator)
  • [...] - Rectangle (process)
  • {...} - Diamond (decision)
  • [/..../] - Parallelogram (input/output)
  • [[...]] - Subroutine (double border)
  • --> - Arrow
  • -->|label| - Labeled arrow

You can add these directly to markdown files and they’ll render in most modern documentation tools.

When Not to Use Flowcharts

Flowcharts aren’t always the right tool:

Use flowcharts for:

  • Algorithms and logic
  • Process flows with decisions
  • Troubleshooting guides
  • Deployment procedures

Don’t use flowcharts for:

  • System architecture (use block diagrams or component diagrams)
  • Data models (use ER diagrams)
  • Time-based interactions (use sequence diagrams)
  • Class relationships (use class diagrams)

Tools for Drawing Flowcharts

Mermaid (my preference):

  • Write flowcharts in text
  • Version control friendly
  • Renders in markdown
  • Free and open source

Lucidchart:

  • Drag-and-drop interface
  • Good for non-technical users
  • Collaboration features
  • Paid (free tier limited)

Draw.io (diagrams.net):

  • Free and open source
  • Desktop or web-based
  • Export to many formats
  • More manual than Mermaid

Graphviz:

  • Text-based like Mermaid
  • Very powerful for complex graphs
  • Steeper learning curve
  • Great for automated diagram generation

My Take

I still draw flowcharts regularly. When debugging a production issue, I’ll sketch the request flow to find where it’s breaking. When designing a new feature, I’ll flowchart the logic before writing code.

The key is keeping them simple. One decision per diamond. One action per box. Clear labels. If your flowchart is too complex to fit on a screen, break it into smaller diagrams.

And if you’re writing documentation, embed flowcharts directly in markdown using Mermaid. Your future self (and your teammates) will thank you.

Resources


Related Posts:

comments powered by Disqus

© 2025 Santosh Manoharan