DiagramKit
Sign InGet Started

Software Development Workflows

Technical flowchart patterns for developers - API flows, deployment pipelines, authentication, error handling, and microservices architecture

Last updated: January 13, 2025
15 min read read

Software Development Workflows

Software developers use flowcharts to design systems, document APIs, plan deployment pipelines, and communicate technical architecture. This tutorial teaches developer-specific flowcharting patterns with practical examples you can use immediately.

What You'll Learn

  • Creating API request/response flowcharts
  • Documenting authentication and authorization flows
  • Mapping deployment pipelines and CI/CD workflows
  • Representing asynchronous operations
  • Error handling and retry logic patterns
  • Microservices communication diagrams
  • Database transaction flows
  • Code-to-flowchart mapping techniques

Prerequisites

  • Software development experience
  • Basic flowcharting knowledge
  • Understanding of Best Practices
  • 30-40 minutes

Example 1: REST API Request Flow

Let's create a comprehensive flowchart for a REST API endpoint that handles user profile updates.

Scenario

Endpoint: PUT /api/users/{userId}/profile

Purpose: Update user profile information with authentication, validation, and database persistence

Technical Stack:

  • Express.js API
  • JWT authentication
  • PostgreSQL database
  • Redis cache
  • S3 for file storage

Step 1: Create the API Flow Structure

  1. Create a new flowchart: "API - Update User Profile"

  2. Add the entry point:

    • Start/End: "HTTP PUT /api/users/:id"
  3. Add authentication layer:

    • Process: "Extract JWT Token from Headers"
    • Decision: "Token Present?"
      • No → Process: "Return 401 Unauthorized" → End
      • Yes → Continue
  4. Add token validation:

    • Process: "Verify JWT Signature"
    • Decision: "Token Valid?"
      • No → Process: "Return 401 Invalid Token" → End
      • Yes → Continue
  5. Add authorization:

    • Process: "Extract User ID from Token"
    • Decision: "Token User ID Matches Request User ID?"
      • No → Process: "Return 403 Forbidden" → End
      • Yes → Continue

Step 2: Add Request Processing

  1. Input validation:

    • Process: "Parse Request Body"
    • Process: "Validate Request Schema"
    • Decision: "Valid Request?"
      • No → Process: "Return 400 Bad Request with Errors" → End
      • Yes → Continue
  2. Business logic validation:

    • Process: "Check Email Uniqueness"
    • Decision: "Email Available?"
      • No → Process: "Return 409 Conflict - Email Exists" → End
      • Yes → Continue

Step 3: Add Database Operations

  1. Database transaction:

    • Process: "Begin Database Transaction"
    • Database: "Query Current User Record"
    • Decision: "User Found?"
      • No → Process: "Rollback Transaction" → "Return 404 Not Found" → End
      • Yes → Continue
  2. Update operations:

    • Database: "UPDATE users SET ... WHERE id = ?"
    • Decision: "Update Successful?"
      • No → Process: "Rollback Transaction" → "Return 500 Database Error" → End
      • Yes → Continue
  3. Commit and finalize:

    • Process: "Commit Transaction"
    • Database: "Invalidate User Cache in Redis"
    • Process: "Return 200 OK with Updated User" → End

Complete API Flow Pattern

Start: HTTP PUT /api/users/:id
  ↓
Extract JWT Token (Process)
  ↓
Token Present? (Decision)
  ├→ No → Return 401 Unauthorized → End
  └→ Yes → Verify JWT Signature
              ↓
            Token Valid? (Decision)
              ├→ No → Return 401 Invalid Token → End
              └→ Yes → Extract User ID from Token
                          ↓
                        User ID Matches? (Decision)
                          ├→ No → Return 403 Forbidden → End
                          └→ Yes → Parse Request Body
                                      ↓
                                    Validate Schema
                                      ↓
                                    Valid? (Decision)
                                      ├→ No → Return 400 Bad Request → End
                                      └→ Yes → Check Email Uniqueness (Database)
                                                  ↓
                                                Email Available? (Decision)
                                                  ├→ No → Return 409 Conflict → End
                                                  └→ Yes → Begin Transaction (Database)
                                                              ↓
                                                            Query User (Database)
                                                              ↓
                                                            User Found? (Decision)
                                                              ├→ No → Rollback → Return 404 → End
                                                              └→ Yes → Update User (Database)
                                                                          ↓
                                                                        Update Success? (Decision)
                                                                          ├→ No → Rollback → Return 500 → End
                                                                          └→ Yes → Commit Transaction
                                                                                      ↓
                                                                                    Invalidate Cache (Database)
                                                                                      ↓
                                                                                    Return 200 OK → End

Developer Tip: Use HTTP status codes in your response labels (401, 403, 404, 409, 500). This makes the API contract clear and helps frontend developers understand expected responses.

Example 2: Authentication Flow with JWT

Let's map a complete authentication system with login, token refresh, and logout.

Login Flow

  1. User Login Request:

    • Start: "POST /api/auth/login"
    • Data I/O: "Receive Credentials (email, password)"
    • Process: "Validate Request Schema"
    • Decision: "Valid Format?"
      • No → Return 400 → End
      • Yes → Continue
  2. User Verification:

    • Database: "Query User by Email"
    • Decision: "User Found?"
      • No → Process: "Return 401 Invalid Credentials" → End
      • Yes → Continue
    • Process: "Compare Password Hash with bcrypt"
    • Decision: "Password Match?"
      • No → Database: "Log Failed Login Attempt" → Return 401 → End
      • Yes → Continue
  3. Account Status Check:

    • Decision: "Account Active?"
      • No → Return 403 Account Disabled → End
      • Yes → Continue
    • Decision: "Email Verified?"
      • No → Return 403 Verify Email → End
      • Yes → Continue
  4. Token Generation:

    • Process: "Generate Access Token (JWT, 15min expiry)"
    • Process: "Generate Refresh Token (JWT, 7 days expiry)"
    • Database: "Store Refresh Token Hash in Database"
    • Database: "Update Last Login Timestamp"
    • Process: "Return Tokens + User Data" → End

Token Refresh Flow

  1. Refresh Request:

    • Start: "POST /api/auth/refresh"
    • Process: "Extract Refresh Token from Request"
    • Decision: "Token Present?"
      • No → Return 401 → End
      • Yes → Continue
  2. Token Validation:

    • Process: "Verify Refresh Token Signature"
    • Decision: "Signature Valid?"
      • No → Return 401 Invalid Token → End
      • Yes → Continue
    • Decision: "Token Not Expired?"
      • No → Return 401 Token Expired → End
      • Yes → Continue
  3. Database Verification:

    • Process: "Extract User ID from Token"
    • Database: "Query Stored Refresh Token"
    • Decision: "Token Exists in Database?"
      • No → Return 401 Token Revoked → End
      • Yes → Continue
  4. New Token Generation:

    • Process: "Generate New Access Token"
    • Process: "Generate New Refresh Token"
    • Database: "Update Stored Refresh Token"
    • Process: "Return New Tokens" → End

Logout Flow

  1. Logout Request:
    • Start: "POST /api/auth/logout"
    • Process: "Extract Refresh Token"
    • Database: "Delete Refresh Token from Database"
    • Database: "Add Access Token to Blacklist (Redis, TTL = token expiry)"
    • Process: "Return 200 OK" → End

Security Best Practice: Always invalidate refresh tokens on logout and store them securely. Use token blacklisting for immediate access token revocation when needed.

Example 3: CI/CD Deployment Pipeline

Document your deployment process from code commit to production.

Pipeline Stages

  1. Trigger:

    • Start: "Git Push to Main Branch"
    • Process: "GitHub Webhook Triggers CI"
  2. Build Stage:

    • Process: "Checkout Code"
    • Process: "Install Dependencies (npm ci)"
    • Process: "Run TypeScript Compilation"
    • Decision: "Build Successful?"
      • No → Process: "Notify Team (Slack)" → End
      • Yes → Continue
  3. Test Stage:

    • Process: "Run Unit Tests (Jest)"
    • Decision: "Tests Pass?"
      • No → Notify Team → End
      • Yes → Continue
    • Process: "Run Integration Tests"
    • Decision: "Tests Pass?"
      • No → Notify Team → End
      • Yes → Continue
  4. Security Scanning:

    • Process: "Run Dependency Audit (npm audit)"
    • Decision: "Critical Vulnerabilities?"
      • Yes → Notify Team → End
      • No → Continue
    • Process: "Run SAST (Static Analysis)"
    • Decision: "Security Issues?"
      • Yes → Notify Team → End
      • No → Continue
  5. Build Artifacts:

    • Process: "Build Docker Image"
    • Process: "Tag Image with Git Commit SHA"
    • Process: "Push to Container Registry"
  6. Staging Deployment:

    • Process: "Deploy to Staging Environment"
    • Process: "Run Smoke Tests"
    • Decision: "Smoke Tests Pass?"
      • No → Rollback → Notify Team → End
      • Yes → Continue
    • Process: "Run E2E Tests (Playwright)"
    • Decision: "E2E Tests Pass?"
      • No → Rollback → Notify Team → End
      • Yes → Continue
  7. Production Approval:

    • Decision: "Auto-Deploy to Production?"
      • No → Process: "Wait for Manual Approval" → Decision: "Approved?"
        • No → End
        • Yes → Continue
      • Yes → Continue
  8. Production Deployment:

    • Process: "Deploy to Production (Blue-Green)"
    • Process: "Run Health Checks"
    • Decision: "Health Checks Pass?"
      • No → Process: "Automatic Rollback" → Notify Team → End
      • Yes → Continue
    • Process: "Switch Traffic to New Version"
    • Process: "Monitor Metrics (5 minutes)"
    • Decision: "Error Rate Normal?"
      • No → Automatic Rollback → Notify Team → End
      • Yes → Continue
  9. Finalize:

    • Process: "Notify Team - Deploy Success"
    • Process: "Create Release Notes"
    • Database: "Record Deployment in Audit Log"
    • End: "Deployment Complete"

DevOps Tip: Include rollback decision points after each deployment stage. Automated rollback on failed health checks prevents prolonged outages.

Example 4: Asynchronous Job Processing

Map background job processing with queues and workers.

Background Job System

  1. Job Creation:

    • Start: "API Request: Process Large File"
    • Process: "Validate File Upload"
    • Process: "Save File to S3"
    • Process: "Create Job Record in Database"
    • Process: "Enqueue Job to Redis Queue"
    • Process: "Return Job ID to Client (202 Accepted)" → End (API)
  2. Parallel Worker Process:

    • Start: "Worker: Poll Queue"
    • Decision: "Job Available?"
      • No → Process: "Wait 5 Seconds" → Back to Poll
      • Yes → Continue
    • Process: "Dequeue Job"
    • Database: "Update Job Status to 'Processing'"
  3. Job Processing:

    • Process: "Download File from S3"
    • Process: "Process File (Chunks)"
    • Decision: "Processing Successful?"
      • No → Handle Error (below)
      • Yes → Continue
  4. Success Path:

    • Process: "Upload Results to S3"
    • Database: "Update Job Status to 'Complete'"
    • Process: "Send Webhook Notification"
    • Database: "Queue Cleanup Job"
    • End: "Job Complete"
  5. Error Handling:

    • Database: "Increment Retry Count"
    • Decision: "Retry Count < 3?"
      • Yes → Process: "Re-enqueue with Exponential Backoff" → End
      • No → Continue
    • Database: "Update Job Status to 'Failed'"
    • Process: "Send Error Notification"
    • Database: "Log Error Details"
    • End: "Job Failed"

Checking Job Status (Separate Flow)

  1. Status Check:
    • Start: "GET /api/jobs/"
    • Database: "Query Job Record"
    • Decision: "Job Found?"
      • No → Return 404 → End
      • Yes → Continue
    • Process: "Return Job Status (pending/processing/complete/failed)"
    • End

Architecture Pattern: Asynchronous job processing decouples long-running operations from API requests. Always provide status endpoints for clients to poll job progress.

Example 5: Microservices Communication

Document inter-service communication patterns.

Synchronous REST Call Pattern

Service A: Process Order
  ↓
HTTP Call: GET /api/inventory/check
  ↓
Service B: Inventory Service
  ↓
Query Database (Database)
  ↓
Return Stock Level
  ↓
Service A: Receive Response
  ↓
Stock Available? (Decision)
  ├→ No → Return 409 Out of Stock → End
  └→ Yes → Continue Order Processing

Asynchronous Event-Driven Pattern

  1. Event Publisher (Service A):

    • Process: "Order Created"
    • Process: "Publish 'OrderCreated' Event to Message Bus"
    • End
  2. Event Consumer (Service B - Inventory):

    • Start: "Subscribe to 'OrderCreated' Events"
    • Process: "Receive Event"
    • Process: "Decrease Stock Quantity"
    • Database: "Update Inventory Database"
    • Process: "Publish 'InventoryUpdated' Event"
    • End
  3. Event Consumer (Service C - Notification):

    • Start: "Subscribe to 'OrderCreated' Events"
    • Process: "Receive Event"
    • Process: "Send Confirmation Email"
    • End

Saga Pattern (Distributed Transaction)

Document compensating transactions for failures:

Start: Create Order Saga
  ↓
Service A: Reserve Inventory
  ↓
Success? (Decision)
  ├→ No → End Saga (Failed)
  └→ Yes → Service B: Process Payment
              ↓
            Success? (Decision)
              ├→ No → Compensate: Release Inventory → End Saga (Failed)
              └→ Yes → Service C: Schedule Shipping
                          ↓
                        Success? (Decision)
                          ├→ No → Compensate: Refund Payment
                          |       ↓
                          |     Compensate: Release Inventory
                          |       ↓
                          |     End Saga (Failed)
                          └→ Yes → Commit Saga (Success) → End

Distributed Systems: Always plan for partial failures in microservices. Use saga patterns or two-phase commits for transactions spanning multiple services.

Technical Shape Usage Guide

When to Use Each Shape

ShapeSoftware ContextExamples
ProcessAny computation or operation"Hash Password", "Parse JSON", "Calculate Total"
DecisionConditional logic"User Authorized?", "Response Status 200?", "Retry?"
Data I/OExternal input/output"Receive HTTP Request", "Return Response", "Read File"
DatabaseData persistence operations"Query Users", "Save Record", "Update Cache"
DocumentFile operations"Generate PDF", "Write Log File", "Export CSV"
CloudExternal service calls"S3 Upload", "API Call", "Email Service"
DelayTimeouts and waiting"Wait 30 Seconds", "Retry After 5s", "Rate Limit"

Code-to-Flowchart Mapping

Code Block:

async function updateUser(userId: string, data: UpdateUserDTO) {
  // Validate input
  if (!isValid(data)) {
    throw new ValidationError("Invalid data");
  }

  // Check permissions
  if (!hasPermission(userId)) {
    throw new ForbiddenError("No permission");
  }

  // Update database
  const user = await db.users.update({
    where: { id: userId },
    data: data
  });

  // Invalidate cache
  await cache.delete(`user:${userId}`);

  return user;
}

Flowchart:

Start: updateUser(userId, data)
  ↓
Validate Input (Process)
  ↓
Valid? (Decision)
  ├→ No → Throw ValidationError → End
  └→ Yes → Check Permissions
              ↓
            Has Permission? (Decision)
              ├→ No → Throw ForbiddenError → End
              └→ Yes → Update User Record (Database)
                          ↓
                        Delete Cache Entry (Database)
                          ↓
                        Return User → End

Error Handling Patterns

Retry with Exponential Backoff

Start: API Call
  ↓
Attempt API Request (Process)
  ↓
Success? (Decision)
  ├→ Yes → Return Result → End
  └→ No → Increment Retry Count
              ↓
            Retry Count <= 3? (Decision)
              ├→ No → Throw Error → End
              └→ Yes → Calculate Backoff (2^retry * 1000ms)
                          ↓
                        Wait (Delay)
                          ↓
                        (Back to Attempt API Request)

Circuit Breaker Pattern

Start: Service Call
  ↓
Check Circuit State (Decision)
  ├→ Open → Return Cached/Default Response → End
  ├→ Half-Open → Attempt Request
  |               ↓
  |             Success? (Decision)
  |               ├→ Yes → Close Circuit → Return Response → End
  |               └→ No → Open Circuit → Return Error → End
  └→ Closed → Attempt Request
                  ↓
                Success? (Decision)
                  ├→ Yes → Return Response → End
                  └→ No → Increment Failure Count
                              ↓
                            Failures >= Threshold? (Decision)
                              ├→ Yes → Open Circuit → Return Error → End
                              └→ No → Return Error → End

Graceful Degradation

Start: Feature Request
  ↓
Try Primary Service
  ↓
Success? (Decision)
  ├→ Yes → Return Full Feature → End
  └→ No → Try Secondary Service
              ↓
            Success? (Decision)
              ├→ Yes → Return Partial Feature → End
              └→ No → Return Cached Data
                          ↓
                        Cache Available? (Decision)
                          ├→ Yes → Return Stale Data → End
                          └→ No → Return Default/Error → End

Database Transaction Patterns

Optimistic Locking

Start: Update Record
  ↓
Read Current Record + Version (Database)
  ↓
Modify Record Locally (Process)
  ↓
Update WHERE id = X AND version = Y (Database)
  ↓
Rows Affected > 0? (Decision)
  ├→ Yes → Commit → End
  └→ No → Record Changed by Another Process
              ↓
            Retry? (Decision)
              ├→ Yes → (Back to Read Current Record)
              └→ No → Throw ConcurrencyError → End

Two-Phase Commit

Start: Distributed Transaction
  ↓
Phase 1: Prepare
  ↓
Send Prepare to All Participants
  ↓
All Participants Ready? (Decision)
  ├→ No → Send Abort to All → Rollback → End
  └→ Yes → Phase 2: Commit
              ↓
            Send Commit to All Participants
              ↓
            All Committed? (Decision)
              ├→ No → Send Rollback to Failed → Log Error → End
              └→ Yes → Transaction Complete → End

Pro Tips for Software Workflows

Layer Your Diagrams: Create high-level architecture flowcharts, then detailed flowcharts for each component. Link them using off-page connectors.

Version Control: Store flowcharts alongside code in Git. Update flowcharts during code reviews to keep documentation current.

Use Consistent Naming: Match flowchart labels to actual function/method names in your code for easy correlation.

Document Error Codes: Include specific error codes and HTTP status codes in your flowcharts for API documentation.

Show Timeouts: Always include timeout handling in external service calls. Add Delay shapes to show wait times.

Common Use Cases

1. API Documentation

Generate flowcharts for all public API endpoints showing request validation, authentication, business logic, and responses.

2. Onboarding New Developers

Create flowcharts of complex systems to help new team members understand architecture faster than reading code.

3. System Design Interviews

Use flowcharts to explain your approach to distributed systems, caching strategies, and scalability solutions.

4. Incident Response

Document incident response procedures with clear flowcharts showing escalation paths and remediation steps.

5. Code Review Discussions

Create flowcharts during design reviews to align the team before writing code.

6. Technical Specifications

Include flowcharts in technical specs to complement written descriptions of system behavior.

Next Steps

  1. Document Your APIs - Create flowcharts for your most-used API endpoints
  2. Map Your Deploy Process - Document CI/CD pipeline for your team
  3. Create Architecture Diagrams - Map microservices interactions
  4. Build Pattern Library - Create reusable flowchart patterns for common operations
  5. Integrate with Code - Store flowcharts in your repository alongside code

Related Documentation


Start diagramming your code today! Well-documented systems are easier to maintain, scale, and onboard new developers. Use flowcharts to make your technical architecture clear to everyone on your team.