<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sanjay Vadhiya</title>
    <description>The latest articles on DEV Community by Sanjay Vadhiya (@sanjay7827).</description>
    <link>https://dev.to/sanjay7827</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4143243%2F555f9220-bd9c-42cc-a65b-43b47912db7b.png</url>
      <title>DEV Community: Sanjay Vadhiya</title>
      <link>https://dev.to/sanjay7827</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanjay7827"/>
    <language>en</language>
    <item>
      <title>AI + Temporal in .NET 10: Building Reliable AI Workflows</title>
      <dc:creator>Sanjay Vadhiya</dc:creator>
      <pubDate>Mon, 05 Oct 2026 03:24:54 +0000</pubDate>
      <link>https://dev.to/sanjay7827/ai-temporal-in-net-10-building-reliable-ai-workflows-342j</link>
      <guid>https://dev.to/sanjay7827/ai-temporal-in-net-10-building-reliable-ai-workflows-342j</guid>
      <description>&lt;p&gt;&lt;strong&gt;AI applications are no longer just:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
   ↓
AI Model
   ↓
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-world AI applications often involve multiple steps:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
     ↓
AI Analysis
     ↓
External API
     ↓
Database
     ↓
Human Approval
     ↓
Final Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;But what happens if the AI API fails?&lt;/li&gt;
&lt;li&gt;What if the application crashes halfway through the workflow?&lt;/li&gt;
&lt;li&gt;What if a human needs to approve something tomorrow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;Temporal&lt;/strong&gt; can be useful.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI provides intelligence. Temporal provides reliable workflow execution.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why Combine AI with Temporal?
&lt;/h2&gt;

&lt;p&gt;Imagine an AI-powered order review system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Created
     ↓
Charge Payment
     ↓
AI Risk Analysis
     ↓
Check Risk
   /       \
Low Risk   High Risk
   ↓          ↓
Continue   Human Review
              ↓
          Approval
              ↓
          Continue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are several things that can fail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI API can be unavailable&lt;/li&gt;
&lt;li&gt;External APIs can timeout&lt;/li&gt;
&lt;li&gt;Workers can restart&lt;/li&gt;
&lt;li&gt;A workflow may need to wait for a human&lt;/li&gt;
&lt;li&gt;An AI operation may need to be retried&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of writing custom infrastructure for all of these situations, Temporal can manage the workflow execution.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Basic Architecture
&lt;/h2&gt;

&lt;p&gt;A simple AI + Temporal architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              ASP.NET Core
                   ↓
             Temporal Server
                   ↓
              .NET Worker
                   ↓
            Temporal Workflow
                   ↓
        ┌──────────┼──────────┐
        ↓          ↓          ↓
       AI       Database    External API
    Activity     Activity      Activity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important separation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Workflow
   ↓
Controls the process

Activity
   ↓
Performs external work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI call should generally be placed inside an Activity because it communicates with an external service.&lt;/p&gt;




&lt;h1&gt;
  
  
  AI as a Temporal Activity
&lt;/h1&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Temporalio.Activities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AiActivities&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;AnalyzeOrderAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Call your AI provider here.&lt;/span&gt;
        &lt;span class="c1"&gt;// OpenAI, Gemini, Azure OpenAI,&lt;/span&gt;
        &lt;span class="c1"&gt;// Amazon Bedrock, etc.&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;
            &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"HIGH_RISK"&lt;/span&gt;
            &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"LOW_RISK"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Workflow can then call this Activity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderWorkflow&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;WorkflowRun&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;risk&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteActivityAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AiActivities&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnalyzeOrderAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;StartToCloseTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                        &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Workflow controls &lt;strong&gt;when&lt;/strong&gt; the AI should run.&lt;/p&gt;

&lt;p&gt;The Activity performs the actual AI call.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Happens When AI Fails?
&lt;/h1&gt;

&lt;p&gt;Suppose the AI provider temporarily returns an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Activity
     ↓
503 Service Unavailable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of immediately losing the workflow, Temporal can retry the Activity according to a configured retry policy.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt 1 → Failed
     ↓
   Retry
     ↓
Attempt 2 → Failed
     ↓
   Retry
     ↓
Attempt 3 → Success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes especially useful when your workflow depends on multiple external services.&lt;/p&gt;

&lt;p&gt;Of course, not every error should be retried. Production applications should define appropriate retry policies for rate limits, timeouts, temporary failures, and permanent errors.&lt;/p&gt;




&lt;h1&gt;
  
  
  AI + Human-in-the-Loop
&lt;/h1&gt;

&lt;p&gt;One of the most useful patterns is combining AI with human approval.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Analysis
     ↓
Risk Check
     ↓
High Risk
     ↓
Human Review
     ↓
WAIT
     ↓
Manager Approves
     ↓
Workflow Continues
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manager might approve the order several hours or even days later.&lt;/p&gt;

&lt;p&gt;Temporal supports mechanisms such as &lt;strong&gt;Signals&lt;/strong&gt; that allow external applications to communicate with a running workflow.&lt;/p&gt;

&lt;p&gt;This means you don't need to keep a .NET thread running while waiting for the manager.&lt;/p&gt;

&lt;p&gt;The workflow can wait for the event and continue when the approval arrives.&lt;/p&gt;




&lt;h1&gt;
  
  
  AI Agents + Temporal
&lt;/h1&gt;

&lt;p&gt;This idea can also be extended to AI agents.&lt;/p&gt;

&lt;p&gt;Imagine an AI agent that needs to call several tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
     ↓
AI Agent
     ↓
Search API
     ↓
Database
     ↓
Payment API
     ↓
AI Evaluation
     ↓
Final Result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temporal can orchestrate this process and provide durable execution around the individual operations.&lt;/p&gt;

&lt;p&gt;This is particularly useful when an AI agent performs important business operations rather than simply generating text.&lt;/p&gt;




&lt;h1&gt;
  
  
  When Should You Use Temporal with AI?
&lt;/h1&gt;

&lt;p&gt;Temporal can be a good choice when your AI workflow is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-step&lt;/li&gt;
&lt;li&gt;Long-running&lt;/li&gt;
&lt;li&gt;Dependent on external services&lt;/li&gt;
&lt;li&gt;Failure-prone&lt;/li&gt;
&lt;li&gt;Waiting for human approval&lt;/li&gt;
&lt;li&gt;Performing important business operations&lt;/li&gt;
&lt;li&gt;Required to survive application restarts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a simple application like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP Request
     ↓
AI API
     ↓
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temporal may be unnecessary.&lt;/p&gt;

&lt;p&gt;The goal isn't to add Temporal to every AI application.&lt;/p&gt;

&lt;p&gt;The goal is to use it when the &lt;strong&gt;workflow itself needs reliable execution&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Simple Mental Model
&lt;/h1&gt;

&lt;p&gt;Think about the responsibilities like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI
 ↓
"Analyze this."

Temporal
 ↓
"Make sure this entire process reliably executes."

ASP.NET Core
 ↓
"Expose the application and APIs."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI handles intelligence.&lt;/p&gt;

&lt;p&gt;Temporal handles orchestration and durable execution.&lt;/p&gt;

&lt;p&gt;ASP.NET Core handles the application layer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;AI is becoming an important part of modern .NET applications, but production AI systems need more than a good model.&lt;/p&gt;

&lt;p&gt;They also need reliable workflows.&lt;/p&gt;

&lt;p&gt;That's where Temporal becomes interesting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI
 +
Temporal
 +
.NET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be used to build workflows that combine AI models, databases, APIs, messaging systems, and human approval while handling failures and long-running processes.&lt;/p&gt;

&lt;p&gt;The key takeaway:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't make AI responsible for the entire workflow. Let AI provide intelligence and let Temporal orchestrate the process reliably.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That combination can be especially powerful for AI-powered applications where reliability matters as much as intelligence.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dotnet</category>
      <category>automation</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Beyond Background Jobs: Building Durable Workflows with Temporal and .NET 10</title>
      <dc:creator>Sanjay Vadhiya</dc:creator>
      <pubDate>Mon, 05 Oct 2026 03:23:54 +0000</pubDate>
      <link>https://dev.to/sanjay7827/beyond-background-jobs-building-durable-workflows-with-temporal-and-net-10-54ll</link>
      <guid>https://dev.to/sanjay7827/beyond-background-jobs-building-durable-workflows-with-temporal-and-net-10-54ll</guid>
      <description>&lt;p&gt;If you've worked with .NET applications, you've probably written code like this:&lt;/p&gt;

&lt;p&gt;await ChargePayment();&lt;br&gt;
await ReserveInventory();&lt;br&gt;
await GenerateInvoice();&lt;br&gt;
await SendEmail();&lt;/p&gt;

&lt;p&gt;It looks simple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;But what happens if the application crashes after &lt;strong&gt;ReserveInventory()&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What happens if the payment API is temporarily unavailable?&lt;/li&gt;
&lt;li&gt;What happens if the workflow needs to wait for a manager's approval for two days?&lt;/li&gt;
&lt;li&gt;What happens if the server restarts while the workflow is running?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build solutions for all of these problems yourself, but the amount of infrastructure and error-handling code can grow quickly.&lt;/p&gt;

&lt;p&gt;This is where Temporal comes in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Temporal is a durable workflow execution platform that helps applications reliably execute long-running and failure-prone workflows.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we'll build a simple order-processing workflow using .NET 10 and Temporal and understand the concepts behind it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Temporal?
&lt;/h2&gt;

&lt;p&gt;Temporal allows you to define a business process as a workflow and execute it reliably.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fijpbch3mewf92ai8amhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fijpbch3mewf92ai8amhe.png" alt=" " width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of treating these as unrelated background jobs, Temporal lets us model them as one workflow.&lt;/p&gt;

&lt;p&gt;The important part isn't just running these steps.&lt;/p&gt;

&lt;p&gt;The important part is that Temporal keeps track of the workflow's execution so that it can recover from failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conceptually:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         Temporal
            |
            ↓
    Order Processing
            |
   ┌────────┼────────┐
   ↓        ↓        ↓
Payment  Inventory  Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If something goes wrong, the workflow can retry activities or continue from the appropriate point.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why do we need Temporal?
&lt;/h2&gt;

&lt;p&gt;Let's start with a normal ASP.NET Core application.&lt;/p&gt;

&lt;p&gt;Imagine this method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task ProcessOrder()
{
    await ChargePayment();
    await ReserveInventory();
    await GenerateInvoice();
    await SendEmail();
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now imagine this sequence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Charge Payment       ✓&lt;/li&gt;
&lt;li&gt;Reserve Inventory    ✓&lt;/li&gt;
&lt;li&gt;Generate Invoice     ✗&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maybe the invoice service is temporarily unavailable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You now need to think about:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should the invoice operation be retried?&lt;/li&gt;
&lt;li&gt;How many times?&lt;/li&gt;
&lt;li&gt;How long should we wait between retries?&lt;/li&gt;
&lt;li&gt;What happens if the application crashes?&lt;/li&gt;
&lt;li&gt;How do we know which steps already completed?&lt;/li&gt;
&lt;li&gt;How do we resume the process?&lt;/li&gt;
&lt;li&gt;What happens if the workflow needs to wait for an external event?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the workflow becomes more complicated, you end up building your own workflow infrastructure.&lt;/p&gt;

&lt;p&gt;Temporal provides infrastructure for these problems.&lt;/p&gt;
&lt;h2&gt;
  
  
  Temporal's Core Concepts
&lt;/h2&gt;

&lt;p&gt;Before writing code, let's understand four important concepts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Workflow&lt;/li&gt;
&lt;li&gt;Activity&lt;/li&gt;
&lt;li&gt;Worker&lt;/li&gt;
&lt;li&gt;Temporal Server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;1. Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Workflow describes the overall business process.&lt;/p&gt;

&lt;p&gt;For our order system:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Order Workflow
|
├── Charge Payment
|
├── Reserve Inventory
|
├── Generate Invoice
|
└── Send Email&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The workflow defines the order in which these operations happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Activity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An Activity performs actual external work.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ChargePayment()&lt;/li&gt;
&lt;li&gt;ReserveInventory()&lt;/li&gt;
&lt;li&gt;GenerateInvoice()&lt;/li&gt;
&lt;li&gt;SendEmail()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Activities are where you normally interact with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;li&gt;Payment gateways&lt;/li&gt;
&lt;li&gt;Email services&lt;/li&gt;
&lt;li&gt;File systems&lt;/li&gt;
&lt;li&gt;External applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful mental model is:&lt;/p&gt;

&lt;p&gt;Workflow = What should happen?&lt;/p&gt;

&lt;p&gt;Activity = Perform the actual work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Worker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Worker is your application process that executes workflows and activities.&lt;/p&gt;

&lt;p&gt;A simplified architecture looks like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            Temporal Server
                  ↑
                  |
             .NET Worker
              /       \
             /         \
      Workflow       Activities
                        |
             ┌──────────┼──────────┐
             ↓          ↓          ↓
          Database    API       Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The Worker polls Temporal for work and executes it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Temporal Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Temporal Server coordinates workflow execution and maintains the information needed for durable execution.&lt;/p&gt;

&lt;p&gt;Your application doesn't simply keep workflow state in memory.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Your Worker
     ↓
Temporal
     ↓
Workflow History&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is one of the fundamental reasons Temporal can recover workflows after failures.&lt;/p&gt;
&lt;h2&gt;
  
  
  Our Example
&lt;/h2&gt;

&lt;p&gt;Let's build an order-processing system.&lt;/p&gt;

&lt;p&gt;The workflow will look like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Order Created
               |
               ↓
         Charge Payment
               |
               ↓
       Check Order Amount
          /          \
   &amp;gt; ₹10,000         &amp;lt;= ₹10,000
       |                  |
       ↓                  ↓
 Manager Approval     Normal Process
       \                  /
        \                /
         ↓              ↓
             Send Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We'll use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET 10&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;Temporal .NET SDK&lt;/li&gt;
&lt;li&gt;ASP.NET Core&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Create the .NET Project
&lt;/h2&gt;

&lt;p&gt;Create a new ASP.NET Core application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dotnet new web -n TemporalDemo&lt;/li&gt;
&lt;li&gt;cd TemporalDemo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Install the Temporal .NET SDK:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dotnet add package Temporalio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You can verify the project:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dotnet run&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 2: Create the Order Model
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Models/OrderRequest.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;CustomerName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our API will receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customerName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sanjay"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Create Activities
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activities/OrderActivities.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Temporalio.Activities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Activities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderActivities&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ChargePaymentAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;$"Charging ₹&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; for &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// In a real application:&lt;/span&gt;
        &lt;span class="c1"&gt;// Call your payment provider here.&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Payment successful"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;RequestManagerApprovalAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;$"Manager approval required for &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: ₹&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// In a real application:&lt;/span&gt;
        &lt;span class="c1"&gt;// Save an approval request to your database&lt;/span&gt;
        &lt;span class="c1"&gt;// or notify a manager.&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;SendEmailAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;$"Sending email to &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// In a real application:&lt;/span&gt;
        &lt;span class="c1"&gt;// Call your email provider.&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the Activities contain the actual work.&lt;/p&gt;

&lt;p&gt;For example, this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ChargePaymentAsync()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;could eventually call Stripe, Razorpay, PayPal, or your own payment API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create the Workflow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflows/OrderWorkflow.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Temporalio.Workflows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Activities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Workflows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderWorkflow&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;WorkflowRun&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;paymentResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteActivityAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderActivities&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ChargePaymentAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;StartToCloseTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                        &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteActivityAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderActivities&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RequestManagerApprovalAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;StartToCloseTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                        &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteActivityAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderActivities&lt;/span&gt; &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="n"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendEmailAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;StartToCloseTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                    &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;paymentResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The workflow says:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Charge payment&lt;/li&gt;
&lt;li&gt;If amount &amp;gt; ₹10,000, request approval&lt;/li&gt;
&lt;li&gt;Send email&lt;/li&gt;
&lt;li&gt;Finish&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Workflow vs Activity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This distinction is extremely important when learning Temporal.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Workflow

if (amount &amp;gt; 10000)
{
    // ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The workflow defines the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Activity]
public async Task&amp;lt;string&amp;gt; ChargePaymentAsync(...)
{
    // External API call
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Activity performs external work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it this way:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Workflow
   |
   +-- Activity → Payment API
   |
   +-- Activity → Database
   |
   +-- Activity → Email API&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;
  
  
  Step 5: Create the Worker
&lt;/h2&gt;

&lt;p&gt;The Worker executes our workflow and activities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worker.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Temporalio.Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Temporalio.Worker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Activities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;TemporalDemo.Workflows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;TemporalClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConnectAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:7233"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TemporalWorker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TemporalWorkerOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"order-task-queue"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddWorkflow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderWorkflow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddAllActivities&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderActivities&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temporal Worker started."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Worker connects to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;localhost:7233&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which is the Temporal service endpoint in our local setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It listens on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order-task-queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for workflow/activity tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Start a Workflow from ASP.NET Core
&lt;/h2&gt;

&lt;p&gt;Your API can start a workflow.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/orders"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; 
    &lt;span class="n"&gt;OrderRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;TemporalClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;;&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;workflowId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
        &lt;span class="s"&gt;$"order-&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderWorkflow&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;;&lt;/span&gt; 
            &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
                &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WorkflowOptions&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workflowId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;TaskQueue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"order-task-queue"&lt;/span&gt; 
        &lt;span class="p"&gt;});&lt;/span&gt; 

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;WorkflowId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;workflowId&lt;/span&gt; 
    &lt;span class="p"&gt;});&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important idea is that your API doesn't need to perform the entire workflow itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It starts the workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;POST /orders
      |
      ↓
ASP.NET Core
      |
      ↓
Start Workflow
      |
      ↓
Temporal
      |
      ↓
.NET Worker
      |
      ↓
OrderWorkflow&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;
  
  
  What Happens When We Send an Order?
&lt;/h2&gt;

&lt;p&gt;Suppose we send:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;POST /orders&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "customerName": "Sanjay",
  "amount": 15000
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The workflow executes:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Order Created
     ↓
Charge Payment
     ↓
₹15,000 &amp;gt; ₹10,000
     ↓
Manager Approval
     ↓
Send Email
     ↓
Completed&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;For an order of ₹5,000:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Order Created
     ↓
Charge Payment
     ↓
₹5,000 &amp;lt;= ₹10,000
     ↓
Skip Manager Approval
     ↓
Send Email
     ↓
Completed&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;
  
  
  What Makes Temporal Different?
&lt;/h2&gt;

&lt;p&gt;So far, this might look like ordinary C#.&lt;/p&gt;

&lt;p&gt;The interesting part starts when things fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imagine:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Charge Payment
      ↓
SUCCESS
      ↓
Manager Approval
      ↓
Server crashes&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A normal in-memory process may lose the current execution state.&lt;/p&gt;

&lt;p&gt;Temporal is designed around durable execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conceptually:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Temporal
   |
   +-- Workflow started
   |
   +-- Payment completed
   |
   +-- Approval started&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the Worker crashes, a new Worker can reconnect to Temporal and continue processing the workflow.&lt;/p&gt;

&lt;p&gt;This is one of Temporal's biggest advantages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity Retries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;External systems fail.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Your Application
      ↓
Payment API
      ↓
503 Service Unavailable&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You don't necessarily want your entire workflow to fail permanently.&lt;/p&gt;

&lt;p&gt;Temporal allows Activities to have retry policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example, conceptually:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Payment Activity
      ↓
Attempt 1 → Failed
      ↓
Wait
      ↓
Attempt 2 → Failed
      ↓
Wait
      ↓
Attempt 3 → Success&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is much safer than implementing random retry loops throughout your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A production retry policy should also consider:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maximum attempts&lt;/li&gt;
&lt;li&gt;Backoff&lt;/li&gt;
&lt;li&gt;Which errors are retryable&lt;/li&gt;
&lt;li&gt;Which errors are permanent&lt;/li&gt;
&lt;li&gt;Activity timeout&lt;/li&gt;
&lt;li&gt;Long-Running Workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Temporal becomes even more useful when a process takes a long time.&lt;/p&gt;

&lt;p&gt;Imagine a purchase that requires manager approval.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Order
 ↓
Payment
 ↓
Request Approval
 ↓
WAIT&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The manager might approve it tomorrow.&lt;/p&gt;

&lt;p&gt;You don't want a .NET thread sitting there doing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;await Task.Delay(
    TimeSpan.FromDays(1)
);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead, Temporal supports durable timers and workflow waiting mechanisms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conceptually:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Workflow
   ↓
Request Approval
   ↓
Wait for Signal
   |
   |  2 days later
   |
Manager Approves
   ↓
Workflow resumes
   ↓
Send Email&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a very different problem from simply running a scheduled background job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temporal Signals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose the workflow is waiting for approval.&lt;/p&gt;

&lt;p&gt;A manager approves the order from an admin application.&lt;/p&gt;

&lt;p&gt;The application can send a signal to the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conceptually:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Admin Application
       |
       | "Approved"
       ↓
Temporal Workflow
       |
       ↓
Resume
       |
       ↓
Ship Order&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This allows external events to interact with running workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if the Worker crashes?
&lt;/h2&gt;

&lt;p&gt;This is one of the first questions you should ask when evaluating Temporal.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Workflow
   ↓
Payment ✓
   ↓
Inventory ✓
   ↓
Worker crashes&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When a Worker becomes available again, Temporal can provide the information needed to continue the workflow.&lt;/p&gt;

&lt;p&gt;This is fundamentally different from relying on variables stored only in your application's memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporal Architecture
&lt;/h2&gt;

&lt;p&gt;At a high level:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               Client
                 |
                 ↓
          ASP.NET Core API
                 |
                 ↓
          Temporal Server
                 |
          Task Queue
                 |
                 ↓
           .NET Worker
                 |
        ┌────────┼────────┐
        ↓        ↓        ↓
    Workflow  Activity  Activity
                  |        |
                  ↓        ↓
               Database  API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;There are three important pieces:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starts or interacts with workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temporal Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Coordinates workflow execution and stores workflow history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Runs your workflow and activity code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporal vs Hangfire
&lt;/h2&gt;

&lt;p&gt;If you've used Hangfire in .NET, you may wonder:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not just use Hangfire?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hangfire is excellent for background jobs.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Every day at 9 AM
       ↓
Generate Report&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Temporal is designed for more complex workflows:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Order
 ↓
Payment
 ↓
Inventory
 ↓
Wait for Approval
 ↓
Shipping
 ↓
Email&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;
  
  
  When Should You Use Temporal?
&lt;/h2&gt;

&lt;p&gt;Temporal makes sense when your workflow is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-running&lt;/li&gt;
&lt;li&gt;Multi-step&lt;/li&gt;
&lt;li&gt;Distributed&lt;/li&gt;
&lt;li&gt;Failure-prone&lt;/li&gt;
&lt;li&gt;Dependent on external services&lt;/li&gt;
&lt;li&gt;Required to survive application restarts&lt;/li&gt;
&lt;li&gt;Waiting for external events&lt;/li&gt;
&lt;li&gt;Important enough that losing state is unacceptable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples include:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fryqevuufxybga2bi6ur1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fryqevuufxybga2bi6ur1.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Travel booking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbgoz0tcdluf1qbojswr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbgoz0tcdluf1qbojswr3.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User onboarding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6mtdfzirnb7gzjybjpqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6mtdfzirnb7gzjybjpqh.png" alt=" " width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkvhehprdw0xh2k4425cs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkvhehprdw0xh2k4425cs.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;create image for this flow&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You NOT Use Temporal?
&lt;/h2&gt;

&lt;p&gt;Temporal isn't something you should add to every application.&lt;/p&gt;

&lt;p&gt;If your requirement is simply:&lt;/p&gt;

&lt;p&gt;Run this method every night&lt;/p&gt;

&lt;p&gt;you probably don't need Temporal.&lt;/p&gt;

&lt;p&gt;Hangfire, Quartz.NET, a cron job or a cloud scheduler may be simpler.&lt;/p&gt;

&lt;p&gt;Likewise, if you just need:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP Request
 ↓
Call API
 ↓
Send Email&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;a simple ASP.NET Core service or an automation platform such as n8n may be more appropriate.&lt;/p&gt;

&lt;p&gt;Use Temporal when the workflow itself is important and needs durable execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Mental Model
&lt;/h2&gt;

&lt;p&gt;Think of these tools like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Hangfire
    ↓
"Run this job."&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;Temporal
    ↓
"Make this workflow reliably execute
even when things fail."&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Temporal isn't just another background-job library.&lt;/p&gt;

&lt;p&gt;Its main idea is durable execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instead of building your own infrastructure for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;workflow state&lt;/li&gt;
&lt;li&gt;timers&lt;/li&gt;
&lt;li&gt;failure recovery&lt;/li&gt;
&lt;li&gt;long-running processes&lt;/li&gt;
&lt;li&gt;external events&lt;/li&gt;
&lt;li&gt;workflow history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you can model your business process as a Temporal workflow and let the Temporal platform handle the execution infrastructure.&lt;/p&gt;

&lt;p&gt;For .NET developers building distributed systems, payment systems, order processing, SaaS platforms, AI pipelines, or other long-running processes, this can be extremely valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  key takeaways:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't think of Temporal as a scheduler. Think of it as infrastructure for reliably executing business processes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't just build workflows that work — build workflows that can survive failures.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you used Temporal or another workflow engine in your .NET projects? Share your experience in the comments.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>automation</category>
      <category>developer</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
