<?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: The Unmeshed Team</title>
    <description>The latest articles on DEV Community by The Unmeshed Team (@unmeshed).</description>
    <link>https://dev.to/unmeshed</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%2F3953781%2F5af20b0f-7da7-4490-9183-a2d28dab3978.png</url>
      <title>DEV Community: The Unmeshed Team</title>
      <link>https://dev.to/unmeshed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unmeshed"/>
    <language>en</language>
    <item>
      <title>Why Do Scheduled Jobs Always Fail at the Worst Time?</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Tue, 14 Jul 2026 06:06:00 +0000</pubDate>
      <link>https://dev.to/unmeshed/why-do-scheduled-jobs-always-fail-at-the-worst-time-3359</link>
      <guid>https://dev.to/unmeshed/why-do-scheduled-jobs-always-fail-at-the-worst-time-3359</guid>
      <description>&lt;h2&gt;
  
  
  Automating Complex Workflows with Scheduled Job
&lt;/h2&gt;

&lt;p&gt;Unmeshed is designed to handle scheduled jobs and batch tasks with ease. It supports complex workflows and executes them with precision, whether you're running them every minute, once a day, once a year or at custom-defined intervals.&lt;/p&gt;

&lt;p&gt;There are countless use cases require running a process on a regular schedule, such as generating monthly budget reports or performing hourly inventory checks. Unmeshed enables this with full support for cron expressions, giving you flexibility and control over your scheduling needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your Schedule in Unmeshed
&lt;/h2&gt;

&lt;p&gt;The Unmeshed UI makes it easy to configure and manage schedules with full visibility. You can select your preferred time zone, choose a start time (immediately or at a future date) and toggle the schedule on or off.&lt;/p&gt;

&lt;p&gt;Another key scheduling feature is the overlap policy. If you have long-running jobs and don't want a new run to start while the last one is still going, simply enable &lt;strong&gt;"Do not allow overlap."&lt;/strong&gt; This ensures only one instance runs at a time, preventing data conflicts and resource contention.&lt;/p&gt;

&lt;p&gt;Once the schedule is live, your process will trigger automatically based on your cron expression. You can monitor future runs and view execution history directly from the &lt;strong&gt;Schedules&lt;/strong&gt; tab.&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%2F6jrkgkcjzddb2z20b3zx.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%2F6jrkgkcjzddb2z20b3zx.png" alt="Unmeshed schedule configuration page showing cron expression setup, timezone selection, overlap policy, and workflow scheduling options." width="800" height="948"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cron Expressions
&lt;/h2&gt;

&lt;p&gt;A cron expression is a simple string format used to define recurring schedules. Unlike interval-based triggers, cron schedules follow a fixed time pattern and do not consider when the last execution finished. This makes them ideal for use cases that require precise timing such as overnight batch jobs, database maintenance, or scheduled report generation.&lt;/p&gt;

&lt;p&gt;Unmeshed supports Unix-cron, which includes five fields. A process is triggered whenever the current time matches the pattern defined by the cron expression. You can write your own cron expressions or use tools like &lt;strong&gt;crontab.co&lt;/strong&gt; to generate them easily and paste them into the Unmeshed UI. Unlike interval-based scheduling, cron jobs do not depend on when the last execution finished and make them ideal for precise timing (e.g., &lt;strong&gt;10:00 PM&lt;/strong&gt; sharp for batch jobs).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * *
| | | | |
| | | | └── day of the week (0–6, starting from Sunday)
| | | └──── month (1–12)
| | └────── day of the month (1–31)
| └──────── hour (0–23)
└────────── minute (0–59)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, for a process to trigger every workday at &lt;strong&gt;10 PM&lt;/strong&gt;, you would use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 22 * * 1-5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Roughly read as: trigger at minute &lt;strong&gt;0&lt;/strong&gt;, hour &lt;strong&gt;22&lt;/strong&gt;, on days &lt;strong&gt;Monday through Friday&lt;/strong&gt;. The asterisk (&lt;code&gt;*&lt;/code&gt;) means that the field is unrestricted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Scheduled Workflows Matter
&lt;/h2&gt;

&lt;p&gt;There are countless real-world scenarios where running a process on a regular cadence is not just helpful, it's essential. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating monthly budget reports&lt;/li&gt;
&lt;li&gt;Performing hourly inventory evaluations&lt;/li&gt;
&lt;li&gt;Running overnight database backups&lt;/li&gt;
&lt;li&gt;Executing regular system maintenance and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unmeshed helps you automate all of these with durable orchestration capability and built-in scheduling features, all without extra scripting or glue code.&lt;/p&gt;

</description>
      <category>workflow</category>
      <category>automation</category>
      <category>devops</category>
      <category>backend</category>
    </item>
    <item>
      <title>Please Stop Sending Secrets Like They're Normal JSON.</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Mon, 13 Jul 2026 08:51:02 +0000</pubDate>
      <link>https://dev.to/unmeshed/please-stop-sending-secrets-like-theyre-normal-json-2nd5</link>
      <guid>https://dev.to/unmeshed/please-stop-sending-secrets-like-theyre-normal-json-2nd5</guid>
      <description>&lt;h2&gt;
  
  
  Secret Inputs When Invoking a Process via Webhook APIs
&lt;/h2&gt;

&lt;p&gt;In orchestration use cases, it's important to pass sensitive or confidential inputs such as tokens, credentials or environment-specific parameters to a workflow securely. This document outlines how to pass such secret data when invoking a process using the Webhook API.&lt;/p&gt;

&lt;p&gt;When invoking a workflow process via Webhook API, secret can be securely included in the request body ensuring that they are not logged or exposed in plain input/output traces. It must only be accessible within the context of the invoked process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Webhooks and Associating Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Process Definition
&lt;/h3&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%2Fwp0gr9gcciw9v80i9zvf.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%2Fwp0gr9gcciw9v80i9zvf.png" alt="Unmeshed process definition showing a webhook triggered workflow that securely accepts secret inputs for API orchestration." width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Webhook Definition
&lt;/h3&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%2Fh27w7grbtcgf711sc08c.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%2Fh27w7grbtcgf711sc08c.png" alt="Webhook definition in Unmeshed showing the webhook configuration, endpoint details, and associated process for securely invoking workflows." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  API Invocation Example
&lt;/h2&gt;

&lt;p&gt;Here is a sample &lt;code&gt;curl&lt;/code&gt; request used to invoke a workflow using the Webhook API, while securely passing secret inputs.&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%2Fxt5wjch1k7r2ukco0zyp.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%2Fxt5wjch1k7r2ukco0zyp.png" alt="Example cURL request showing how to invoke a Unmeshed workflow through a webhook API while securely passing secret inputs using the _secretStatePut field." width="799" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To trigger a workflow in Unmeshed using the Webhook API, you can send a simple POST request with your input data in JSON format. In the example above, the workflow is invoked asynchronously using a secure URL that uniquely identifies the workflow.&lt;/p&gt;

&lt;p&gt;Along with regular inputs like &lt;code&gt;"key1": "value1"&lt;/code&gt;, you can safely pass sensitive data using the &lt;code&gt;_secretStatePut&lt;/code&gt; field, which ensures that secrets such as API keys or credentials are handled securely within the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;code&gt;_secretStatePut&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;_secretStatePut&lt;/code&gt; object allows user to provide inputs that are treated as secrets by the Unmeshed platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not visible in logs or process summaries unless exposed in step's output or in logs of steps.&lt;/li&gt;
&lt;li&gt;Not returned in API responses.&lt;/li&gt;
&lt;li&gt;Accessible only within the running workflow's secured execution context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for passing things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access tokens&lt;/li&gt;
&lt;li&gt;Encrypted configurations&lt;/li&gt;
&lt;li&gt;Internal system credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use this feature for a variety of secure automation scenarios, such as triggering a deployment pipeline with environment-specific credentials, kicking off a data ingestion job that requires access to protected APIs. This lets you run powerful, event-driven automation without exposing sensitive information in your request payload.&lt;/p&gt;

</description>
      <category>security</category>
      <category>api</category>
      <category>devops</category>
      <category>backend</category>
    </item>
    <item>
      <title>Why Do Batch Jobs Still Take All Night?</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Fri, 10 Jul 2026 10:28:37 +0000</pubDate>
      <link>https://dev.to/unmeshed/why-do-batch-jobs-still-take-all-night-126e</link>
      <guid>https://dev.to/unmeshed/why-do-batch-jobs-still-take-all-night-126e</guid>
      <description>&lt;h2&gt;
  
  
  Batch Job Automation with Built-In Job Scheduler
&lt;/h2&gt;

&lt;p&gt;Handling batch jobs are essential in everything from regular data processing and report generation to syncing systems overnight. These jobs often involve predefined sets of steps that need to run at triggered times, and they're expected to do so without manual intervention. Unmeshed makes this easy. In this post, we demonstrate how to automate a complex batch process using the Unmeshed Scheduler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case: Automating Daily API Aggregation Jobs
&lt;/h2&gt;

&lt;p&gt;Let's say your system needs to collect data from &lt;strong&gt;25 different APIs&lt;/strong&gt; every night, to process the responses, and later store the results for further reporting. This is a classic complex batch job made up of multiple steps, and it also running in parallel and triggered regularly. Here's how you can build and automate this job in Unmeshed.&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%2Fv3dvspkvdfmto6qkc92j.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%2Fv3dvspkvdfmto6qkc92j.png" alt="Workflow definition in Unmeshed showing a batch job with multiple parallel HTTP steps for aggregating data from several APIs simultaneously." width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Define the Process
&lt;/h2&gt;

&lt;p&gt;In Unmeshed, start by creating a new process definition. Then name it something like &lt;code&gt;daily_api_aggregation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside the process, use a &lt;strong&gt;Parallel&lt;/strong&gt; task block to handle multiple API calls at once. We'll start with &lt;strong&gt;5 HTTP&lt;/strong&gt; steps inside the parallel block, with each calling a different endpoint.&lt;/p&gt;

&lt;p&gt;To simulate a more complex job, duplicate the block multiple times. In this case, we duplicated it &lt;strong&gt;5 times&lt;/strong&gt;, resulting in &lt;strong&gt;25 parallel HTTP steps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This setup represents a realistic scenario where multiple independent tasks, such as fetching data from different sources, can run simultaneously for efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Test the Performance
&lt;/h2&gt;

&lt;p&gt;Once your workflow is built, you can run a quick test inside Unmeshed.&lt;/p&gt;

&lt;p&gt;In our example, the process executed all &lt;strong&gt;25 HTTP steps&lt;/strong&gt; in under &lt;strong&gt;100 milliseconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the kind of high-performance orchestration Unmeshed delivers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Schedule the Workflow
&lt;/h2&gt;

&lt;p&gt;Now that your process works as expected, it's time to schedule it.&lt;/p&gt;

&lt;p&gt;Unmeshed supports cron expressions. It delivers time-control precision on workflow, whether it's every hour, every Monday at &lt;strong&gt;2 AM&lt;/strong&gt;, or the first day of every month.&lt;/p&gt;

&lt;p&gt;You can create a new schedule in the Unmeshed UI.&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%2F4czswd6jcxvbql6bxq67.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%2F4czswd6jcxvbql6bxq67.png" alt="Batch job scheduler configuration in Unmeshed showing cron scheduling, overlap policy settings, and execution controls for automated workflows." width="800" height="948"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another scheduler feature is the &lt;strong&gt;Overlap Policy&lt;/strong&gt;, which prevents new jobs from starting if the previous one is still running.&lt;/p&gt;

&lt;p&gt;If your batch process sometimes takes longer than expected, setting &lt;strong&gt;Do Not Allow Overlap&lt;/strong&gt; ensures that jobs won't run in parallel unintentionally, preventing data conflicts and system strain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Watch It Run
&lt;/h2&gt;

&lt;p&gt;Once saved, Unmeshed takes care of the rest.&lt;/p&gt;

&lt;p&gt;In our demo, the job is triggered accurately, ran all &lt;strong&gt;25 steps&lt;/strong&gt;, and completed in just &lt;strong&gt;55 milliseconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can view all scheduled executions directly in the UI, giving you complete visibility and confidence.&lt;/p&gt;

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

&lt;p&gt;Log in to Unmeshed and create your first scheduled process today.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>devops</category>
      <category>backend</category>
    </item>
    <item>
      <title>Why Are We Still Downloading Files from SharePoint by Hand?</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Thu, 09 Jul 2026 08:21:14 +0000</pubDate>
      <link>https://dev.to/unmeshed/why-are-we-still-downloading-files-from-sharepoint-by-hand-3cbm</link>
      <guid>https://dev.to/unmeshed/why-are-we-still-downloading-files-from-sharepoint-by-hand-3cbm</guid>
      <description>&lt;h2&gt;
  
  
  Integrating Microsoft SharePoint into the Unmeshed Platform
&lt;/h2&gt;

&lt;p&gt;Microsoft SharePoint is everywhere in the enterprise world. From document management to internal collaboration, it plays a central role in business operations. But when it comes to building durable and scalable automation, SharePoint often feels... limited.&lt;/p&gt;

&lt;p&gt;Unmeshed now includes native Microsoft SharePoint integration, making it easy to connect your SharePoint sites directly to automated workflows.&lt;/p&gt;

&lt;p&gt;Whether you're building AI-powered document processing, approval workflows, or enterprise integrations, SharePoint is now part of your orchestration platform.&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%2Fr3pmmyeclevlmpy2dgwg.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%2Fr3pmmyeclevlmpy2dgwg.png" alt="Microsoft SharePoint integration in Unmeshed showing SharePoint nodes inside the workflow builder for automating file uploads, document processing, and enterprise workflows." width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Do
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Trigger workflows when new files are uploaded
&lt;/h3&gt;

&lt;p&gt;When a user uploads a PDF or document to SharePoint, automatically start a workflow.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Extract data using AI&lt;/li&gt;
&lt;li&gt;Classify documents&lt;/li&gt;
&lt;li&gt;Store results in your database&lt;/li&gt;
&lt;li&gt;Notify downstream systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. React to spreadsheet changes
&lt;/h3&gt;

&lt;p&gt;Automatically detect updates to shared Excel files and sync the latest data with your database, CRM, or data warehouse.&lt;/p&gt;

&lt;p&gt;No manual exports required.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Monitor file changes for audits
&lt;/h3&gt;

&lt;p&gt;Schedule workflows that monitor SharePoint sites and generate reports of file activity.&lt;/p&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security teams&lt;/li&gt;
&lt;li&gt;Compliance reporting&lt;/li&gt;
&lt;li&gt;Audit trails&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Upload generated files back to SharePoint
&lt;/h3&gt;

&lt;p&gt;Generate reports, invoices, exports, or PDFs inside Unmeshed and automatically publish them to the correct SharePoint folder.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Build your own SharePoint experience
&lt;/h3&gt;

&lt;p&gt;Create custom APIs and user interfaces that browse SharePoint files without relying on the default SharePoint UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Getting started takes only a few steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect your SharePoint account.&lt;/li&gt;
&lt;li&gt;Map your SharePoint sites or folders.&lt;/li&gt;
&lt;li&gt;Build workflows visually in the Unmeshed Flow Builder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;You can now trigger workflows from SharePoint events or interact with SharePoint directly as part of larger business processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Most organizations already use SharePoint to store documents.&lt;/p&gt;

&lt;p&gt;The challenge isn't storing files.&lt;/p&gt;

&lt;p&gt;It's everything that happens after a file is uploaded.&lt;/p&gt;

&lt;p&gt;Approvals.&lt;/p&gt;

&lt;p&gt;AI document extraction.&lt;/p&gt;

&lt;p&gt;Notifications.&lt;/p&gt;

&lt;p&gt;Database updates.&lt;/p&gt;

&lt;p&gt;Moving files between teams.&lt;/p&gt;

&lt;p&gt;With native SharePoint integration, these processes become part of one automated workflow instead of a collection of disconnected manual tasks.&lt;/p&gt;

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

&lt;p&gt;SharePoint is a great place to store documents.&lt;/p&gt;

&lt;p&gt;Now it can also become the starting point for durable, scalable workflow automation.&lt;/p&gt;

&lt;p&gt;If your business relies on SharePoint, you can now connect it directly to Unmeshed and automate everything that happens after a document lands in a folder.&lt;/p&gt;

</description>
      <category>sharepoint</category>
      <category>automation</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cron Is Great... Until Your Business Gets Involved</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Wed, 08 Jul 2026 11:47:57 +0000</pubDate>
      <link>https://dev.to/unmeshed/cron-is-great-until-your-business-gets-involved-1dmf</link>
      <guid>https://dev.to/unmeshed/cron-is-great-until-your-business-gets-involved-1dmf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Workflow automation is a critical component of many business operations, handling tasks that require minimal human involvement. From generating financial reports and running overnight data jobs to performing system checks during maintenance windows, automation ensures these processes run efficiently and reliably.&lt;/p&gt;

&lt;p&gt;These processes often rely on recurring execution, traditionally handled with cron expressions. While cron is effective for fixed intervals, it quickly becomes limiting when workflows need to align with real-world business calendars.&lt;/p&gt;

&lt;p&gt;Unmeshed already offers robust cron-based scheduling for repeatable jobs, such as every hour or every day at 5 AM. But for more complex real-world scenarios, we introduced &lt;strong&gt;Calendar Scheduling&lt;/strong&gt;. This feature lets you define custom calendars that act as intelligent filters, ensuring workflows run only on specific and valid days. You can also combine calendars, dynamically generate schedules, and control how jobs respond to skipped or excluded dates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Calendar Types in Unmeshed
&lt;/h2&gt;

&lt;p&gt;Unmeshed supports four calendar types, each built for different scheduling needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List of Dates Calendar&lt;/li&gt;
&lt;li&gt;Code Calendar&lt;/li&gt;
&lt;li&gt;Derived Calendar&lt;/li&gt;
&lt;li&gt;Reschedule Calendar&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. List of Dates Calendar
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;List of Dates Calendar&lt;/strong&gt; allows users to manually select execution dates through the UI.&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%2Ftolcuis3kpxambqg2eq2.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%2Ftolcuis3kpxambqg2eq2.png" alt=" " width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Define a date range and select individual days using a visual calendar.&lt;/li&gt;
&lt;li&gt;Quickly select common patterns such as:

&lt;ul&gt;
&lt;li&gt;Weekends&lt;/li&gt;
&lt;li&gt;Weekdays&lt;/li&gt;
&lt;li&gt;Specific weekdays (for example, every Monday)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Switch between Calendar View and List View to manage selected dates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Non-technical users who prefer visual scheduling.&lt;/li&gt;
&lt;li&gt;Fixed schedules such as monthly reviews or quarterly tasks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Code Calendar
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Code Calendar&lt;/strong&gt; enables developers to generate execution dates programmatically.&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%2Fblvwkq21ezee31imk0n1.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%2Fblvwkq21ezee31imk0n1.png" alt="Code Calendar in Unmeshed showing a JavaScript editor for defining custom scheduling logic and generating workflow execution dates programmatically." width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Write custom logic to generate valid execution dates.&lt;/li&gt;
&lt;li&gt;Use built-in templates to get started quickly.&lt;/li&gt;
&lt;li&gt;Ideal for advanced scheduling scenarios such as:

&lt;ul&gt;
&lt;li&gt;Every third Friday of the month&lt;/li&gt;
&lt;li&gt;First working day after a public holiday&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Logic-driven scheduling.&lt;/li&gt;
&lt;li&gt;Business rules that depend on application data.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Derived Calendar
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Derived Calendar&lt;/strong&gt; combines two existing calendars using set operations.&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%2Fnd32y6rjknp8z2lz0zjb.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%2Fnd32y6rjknp8z2lz0zjb.png" alt="Derived Calendar in Unmeshed showing calendar operations such as Union, Intersection, Difference, and Symmetric Difference to generate execution schedules from existing calendars." width="800" height="763"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UNION&lt;/strong&gt; — Combines all dates from both calendars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INTERSECTION&lt;/strong&gt; — Includes only dates present in both calendars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DIFFERENCE&lt;/strong&gt; — Includes dates from the source calendar that are not in the target calendar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SYMMETRIC DIFFERENCE&lt;/strong&gt; — Includes dates unique to either calendar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Derived calendars cannot be edited manually.&lt;/li&gt;
&lt;li&gt;Dates are automatically computed from the selected calendars and operation.&lt;/li&gt;
&lt;li&gt;Preview the generated schedule before saving.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Combining multiple scheduling rules.&lt;/li&gt;
&lt;li&gt;Excluding holidays from business-day calendars.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Reschedule Calendar
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Reschedule Calendar&lt;/strong&gt; handles situations where scheduled executions need to be postponed instead of skipped.&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%2F45rqj9o4skdkz049ag27.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%2F45rqj9o4skdkz049ag27.png" alt="Reschedule Calendar in Unmeshed showing skipped execution dates, configurable reschedule delays, and calendar-based exception handling for workflow scheduling." width="800" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Skip execution on selected dates, such as holidays or maintenance windows.&lt;/li&gt;
&lt;li&gt;Automatically reschedule skipped jobs after a configurable delay.&lt;/li&gt;
&lt;li&gt;Fine-grained control over exception handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Holiday scheduling.&lt;/li&gt;
&lt;li&gt;Planned maintenance windows.&lt;/li&gt;
&lt;li&gt;Blackout periods.&lt;/li&gt;
&lt;li&gt;Postponing jobs without cancelling them.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Using Calendars in the Job Scheduler
&lt;/h2&gt;

&lt;p&gt;Calendars can be attached to schedules to control &lt;strong&gt;when&lt;/strong&gt; jobs are allowed to run.&lt;/p&gt;

&lt;p&gt;Each schedule can define either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;CRON&lt;/strong&gt; expression, or&lt;/li&gt;
&lt;li&gt;A fixed execution time (for example, &lt;strong&gt;9:00 AM&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a calendar is associated with a schedule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The calendar acts as a filter for eligible execution dates.&lt;/li&gt;
&lt;li&gt;Jobs run only on dates included in the calendar at the configured time.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every calendar includes a preview of future execution dates, making it easy to validate schedules before deployment and avoid unexpected behavior.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Calendar Scheduling gives you fine-grained control over workflow execution by letting calendars filter your schedules.&lt;/p&gt;

&lt;p&gt;Instead of forcing business rules into increasingly complex cron expressions, you can define calendars that reflect how your business actually operates.&lt;/p&gt;

&lt;p&gt;If your workflows depend on holidays, business days, maintenance windows, or custom scheduling rules, calendar-based scheduling provides a much cleaner and more maintainable solution.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>backend</category>
      <category>programming</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why Wait Steps Behave Differently Inside While Loops</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Tue, 07 Jul 2026 10:02:14 +0000</pubDate>
      <link>https://dev.to/unmeshed/why-wait-steps-behave-differently-inside-while-loops-p7p</link>
      <guid>https://dev.to/unmeshed/why-wait-steps-behave-differently-inside-while-loops-p7p</guid>
      <description>&lt;h2&gt;
  
  
  Using Wait Steps in Unmeshed: Handling Delays Inside While Loops
&lt;/h2&gt;

&lt;p&gt;Waiting—whether for a webhook, a human approval, or simply a fixed pause—shows up in almost every orchestration scenario. In Unmeshed, you model these pauses with the &lt;strong&gt;Wait&lt;/strong&gt; step, which accepts a JavaScript function that returns a Unix epoch timestamp (&lt;code&gt;waitUntil&lt;/code&gt;) indicating when the step should complete.&lt;/p&gt;

&lt;p&gt;Most of the time that's all you need. But as soon as you nest a Wait step inside a While loop, an easy-to-miss nuance can trip you up and make the wait look "broken." This post explains that behavior and shows a clean pattern for making loops and waits play nicely together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap: How a Wait Step Works
&lt;/h2&gt;

&lt;p&gt;When the Wait step starts, Unmeshed passes the step's execution context to your JavaScript function. A common implementation adds a fixed offset to the step's start time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// epoch millis when the step first began&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;startDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// wait 3 seconds&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;&lt;code&gt;steps.__self.start&lt;/code&gt; never changes for that step instance, so the first time through everything is perfect: the engine sleeps for three seconds and continues.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gotcha: Wait Inside While
&lt;/h2&gt;

&lt;p&gt;A While step re-executes its inner graph as long as its condition remains true. Each inner step (including Wait) keeps its original start timestamp across iterations. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iteration 0&lt;/strong&gt; – Wait schedules &lt;code&gt;start + 3,000 ms&lt;/code&gt; and pauses. ✅&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iteration 1&lt;/strong&gt; – The same Wait step runs again, but &lt;code&gt;start&lt;/code&gt; is still the original value. Because that timestamp is already in the past, Unmeshed sees that &lt;code&gt;waitUntil&lt;/code&gt; is satisfied and continues immediately. ⚠️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the outside it looks like the engine ignored your wait—but it's really doing exactly what you asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Robust Pattern: Per-Iteration Timestamps
&lt;/h2&gt;

&lt;p&gt;The fix is to track a separate target time for every loop iteration. The snippet below pushes a new timestamp into an &lt;code&gt;iterations&lt;/code&gt; array the first time each iteration executes, then reuses it on retries, restarts, or subsequent checks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Existing array (or []) pulled from the step's previous output&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iterations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;iterations&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentIter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If we haven't stored a target time for this iteration yet, compute &amp;amp; save one&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;currentIter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// wait 3 seconds from *now*&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIter&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// persist the array for next pass&lt;/span&gt;
    &lt;span class="na"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentIter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// optional: surface the index for debugging&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;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idempotent and restart-safe.&lt;/strong&gt; If the engine restarts mid-wait, the stored timestamp is still there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;True per-iteration delay.&lt;/strong&gt; Each loop cycle gets a fresh &lt;code&gt;waitUntil&lt;/code&gt; computed relative to when that cycle began—not when the Wait step was first created.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alternative Approaches
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Context-based key (for example, storing &lt;code&gt;waitUntil&lt;/code&gt; in &lt;code&gt;processContext&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Useful when multiple steps need to reference a shared schedule.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic While condition (moving the timer logic into the While condition itself)&lt;/td&gt;
&lt;td&gt;Handy for simple polling loops where you can express "stop when 3 seconds have passed" directly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Separate Wait step outside While&lt;/td&gt;
&lt;td&gt;Best when you only need one delay before the loop begins.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Best Practices Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Treat Wait steps like any other stateful computation—make them idempotent and restart-safe.&lt;/li&gt;
&lt;li&gt;✅ When looping, compute targets relative to &lt;strong&gt;now&lt;/strong&gt;, not to the original start time.&lt;/li&gt;
&lt;li&gt;✅ Always surface debugging information (such as the current iteration index) in the step output. It makes diagnosing timing issues much easier.&lt;/li&gt;
&lt;li&gt;❌ A Wait step inside a loop does &lt;strong&gt;not&lt;/strong&gt; behave like &lt;code&gt;sleep()&lt;/code&gt; in synchronous code. Remember that the orchestration engine re-evaluates the same node instance on every iteration.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>workflow</category>
      <category>javascript</category>
      <category>devops</category>
      <category>backend</category>
    </item>
    <item>
      <title>How to Build a Scalable Fraud Detection Workflow</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Mon, 06 Jul 2026 10:03:33 +0000</pubDate>
      <link>https://dev.to/unmeshed/how-to-build-a-scalable-fraud-detection-workflow-1ino</link>
      <guid>https://dev.to/unmeshed/how-to-build-a-scalable-fraud-detection-workflow-1ino</guid>
      <description>&lt;h2&gt;
  
  
  The Growing Cost of Fraud
&lt;/h2&gt;

&lt;p&gt;Fraudsters never stop innovating. From synthetic identities to deepfake onboarding, every year brings new tricks to exploit existing systems. The burden of catching fraud in real time falls directly on businesses and the cost of letting it slip through the cracks can be devastating.&lt;/p&gt;

&lt;p&gt;According to Fortune Business Insights the global fraud detection and prevention market was valued at &lt;strong&gt;$52.82 billion&lt;/strong&gt; in 2024 and is projected to exceed &lt;strong&gt;$246 billion&lt;/strong&gt; by 2032. It reflects how serious and expensive the problem has become. Despite this, many organizations are still stuck with manual reviews and disconnected APIs, burning through budgets on processes that software could automate in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Chaos to Clarity: How Unmeshed Streamlines Fraud Detection Pipelines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Case: Onboarding a New Customer via Digital Banking Platform
&lt;/h3&gt;

&lt;p&gt;Meet Alice. She wants to open a digital bank account. Here's how Unmeshed orchestrates the onboarding pipeline to keep Alice and the bank safe:&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%2F57pfsndpi7nt32tzafqv.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%2F57pfsndpi7nt32tzafqv.png" alt="Fraud detection workflow showing a customer onboarding journey where identity verification, risk scoring, business rules, and decision routing are orchestrated through Unmeshed into a single automated pipeline." width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A flow chart demonstrates how the workflow runs seamlessly in Unmeshed:&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%2Fzp4sbh7t8n7y2x4uu8z2.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%2Fzp4sbh7t8n7y2x4uu8z2.png" alt="Fraud detection pipeline visualized in Unmeshed, showing identity verification, risk scoring, decision table evaluation, and automated routing through a low-code workflow builder." width="799" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow in One Glance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fraud_detection_pipeline&lt;/span&gt;

&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;HTTP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# Identity check&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kyc_check&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kyc.example.com/check&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inputs.userId&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;HTTP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# Risk scoring&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;risk_score&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://risk.example.com/score&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;transactionId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inputs.transactionId&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
        &lt;span class="na"&gt;kyc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.kyc_check.response.body&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;DECISIONTABLE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# Rules&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fraud_rules&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;600"&lt;/span&gt;
          &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;outcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BLOCK"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;750"&lt;/span&gt;
          &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;outcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;REVIEW"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;outcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;APPROVE"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;SWITCHCASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="c1"&gt;# Routing&lt;/span&gt;
      &lt;span class="na"&gt;switch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.fraud_rules.outcome&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
      &lt;span class="na"&gt;cases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;BLOCK&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;HTTP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://transactions/block&lt;/span&gt;
        &lt;span class="na"&gt;REVIEW&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;HTTP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://review-queue/enqueue&lt;/span&gt;
        &lt;span class="na"&gt;APPROVE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;HTTP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://transactions/approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unmeshed manages the entire flow of API calls during digital banking onboarding, helping banks cut down on costly developer hours and avoid endless maintenance of fragile scripts, effectively freeing up budget for innovation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Orchestration Saves Money
&lt;/h2&gt;

&lt;p&gt;Instead of throwing more engineers or analysts at the problem, Unmeshed connects all the moving parts into single and automated flow. That shift saves money in three big ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Less Manual Review
&lt;/h3&gt;

&lt;p&gt;Most fraud teams spend hours chasing false positives. Incorporating orchestration automates auto-approves on low-risk transaction; for high-risk case it can be blocked instantly. Human task is required only when the rules say, "required further review".&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Eliminate Fragile Scripts to Maintain
&lt;/h3&gt;

&lt;p&gt;Without orchestration, developer needs to spend substantial time and resources to fix broken script that stitch every API or data source, silently draining budgets and eating up developer’s time. Unmeshed handles the integrations automatically, freeing developers to focus on core work.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Predictable Cost at Any Scale
&lt;/h3&gt;

&lt;p&gt;While it is not possible to fully eliminate fraudulent activities, Unmeshed handles millions of processes at fixed rate only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Unmeshed Complements Fraud Detection Process Using Orchestration Platform
&lt;/h2&gt;

&lt;p&gt;Fraud detection is complex and can’t be stitched together with broken scripts and siloed tools anymore. Unmeshed connects all the APIs and services into one seamless pipeline, so processes flow with little human intervention or brittle scripts.&lt;/p&gt;

&lt;p&gt;Banks today spend millions on fraud analysts chasing false positives. With Unmeshed, one mid-market bank automated 95% of checks, cutting review workload by half.&lt;/p&gt;

&lt;p&gt;Ready to see how Unmeshed can simplify your fraud workflows and save money? Book a demo today.&lt;/p&gt;

</description>
      <category>workflow</category>
      <category>fintech</category>
      <category>api</category>
      <category>devops</category>
    </item>
    <item>
      <title>How Unmeshed Helped Modernize Logistics Software at Scale</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Fri, 03 Jul 2026 11:54:30 +0000</pubDate>
      <link>https://dev.to/unmeshed/how-unmeshed-helped-modernize-logistics-software-at-scale-461m</link>
      <guid>https://dev.to/unmeshed/how-unmeshed-helped-modernize-logistics-software-at-scale-461m</guid>
      <description>&lt;h1&gt;
  
  
  Optimizing Logistics Software with Unmeshed
&lt;/h1&gt;

&lt;p&gt;Learn how Unmeshed orchestration transforms logistics operations through automation of resilient and durable business processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;A leading logistics enterprise operating across North America with businesses ranging from freight brokers to carriers to customer handling through a digital freight platform. As global supply chains evolve and real time observability becomes a competitive necessity, the enterprise set out to modernize its operation to deliver faster and more transparent logistics experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dilemma
&lt;/h2&gt;

&lt;p&gt;With freight volumes surging and new partner systems being added, the enterprise’s logistics stack had grown and becoming fragmented, forcing developers to stitch brittle scripts which hold systems together. Despite their best effort, substantial number of human hours are deployed to handle manual coordination between tools.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Every day, our teams were switching between systems for pricing, tracking, billing, and communication. It wasn’t about lack of technology, rather it was about lack of connection,” explained technical team.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Then we found Unmeshed. It provides orchestration and workflow automation in a low-code environment and still able to code complex logic and custom integrations, we could do everything we wanted in one unified platform,” said the technical team.&lt;/p&gt;

&lt;p&gt;“Once we onboarded with Unmeshed, we were able to create logistics workflows and identified more use cases across other teams or processes. Once the workflow process is fully built in the orchestration platform, those modules can be plugged in anywhere within our workflow.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The core business on any logistics company relies heavily on speed and efficiency, prompting the team to adopt CI/CD approach powered by Unmeshed. Unmeshed introduces a version-controlled orchestration environment to build durable APIs that run at scale. Unit test and integration test are part of the orchestration components ensuring rapid iteration and reliability across their supply chain operations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Unmeshed helped us design an end-to-end orchestration lifecycle,” said the team member overseeing implementation. “The workflows cover key logistics processes such as freight quoting, billing, invoice reconciliation, delivery exception handling and more. Recently, we’ve begun integrating AI-driven decision logic into workflow, to automatically flag anomalies, predict delivery delays and optimize route selections in real time. These reusable and intelligent workflows now serve as foundational building blocks to accelerate future integrations and significantly reduce engineering overhead across the organization.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impact
&lt;/h2&gt;

&lt;p&gt;The results were transformative.&lt;/p&gt;

&lt;p&gt;According to a study published in the &lt;em&gt;International Journal for Multidisciplinary Research (IJFMR)&lt;/em&gt; by Pankaj Singhal (2024), enterprises implementing robust orchestration workflows experience a &lt;strong&gt;47% reduction in service integration failures&lt;/strong&gt;, leading to greater reliability and fewer disruptions across connected systems.&lt;/p&gt;

&lt;p&gt;They also report a &lt;strong&gt;35% improvement in resource utilization&lt;/strong&gt;, as automation eliminates redundant tasks and allows teams to focus on higher-value engineering work. Furthermore, orchestration enables &lt;strong&gt;62% faster deployment cycles&lt;/strong&gt; without increasing infrastructure complexity. Together, these gains demonstrate how intelligent orchestration with Unmeshed can transform logistics operations into scalable and resilient workflow.&lt;/p&gt;

&lt;p&gt;By leveraging Unmeshed orchestration, the logistics enterprise achieved similar operational gains. Unmeshed reduce integration friction to improve efficiency across carrier and shipment workflows, deliver real-time visibility across the logistics chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Step
&lt;/h2&gt;

&lt;p&gt;Schedule a Consultation with Unmeshed to streamline your TMS, CRM and carrier systems into resilient automation layer that drives scale and ensure compliance, together with real-time intelligence across your supply chain.&lt;/p&gt;

&lt;p&gt;Happy Orchestrating.&lt;/p&gt;

</description>
      <category>logistics</category>
      <category>devops</category>
      <category>microservices</category>
      <category>cloud</category>
    </item>
    <item>
      <title>The Trade-Offs of AWS Step Functions (and Why Some Teams Move Beyond It)</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Wed, 01 Jul 2026 11:05:02 +0000</pubDate>
      <link>https://dev.to/unmeshed/the-trade-offs-of-aws-step-functions-and-why-some-teams-move-beyond-it-2e5o</link>
      <guid>https://dev.to/unmeshed/the-trade-offs-of-aws-step-functions-and-why-some-teams-move-beyond-it-2e5o</guid>
      <description>&lt;p&gt;As enterprises scale, AWS Step Functions is a popular choice to automate distributed workflows, all within AWS ecosystem. But many teams face recurring challenges as they scale, challenges that limit flexibility. In this blog, we will highlight those challenges and to show you that Unmeshed could be the practical and modern solutions for today’s API-driven and AI-powered environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 1: Cost
&lt;/h2&gt;

&lt;p&gt;When workflows volumes grow into the millions, Step Functions quickly become expensive and operationally heavy due to per-state billing and limited scaling flexibility, whereas Unmeshed offers fixed price, eliminating per-state billing entirely. It runs orchestration directly on lightweight infrastructure cutting both compute and operational costs. We offer massive saving as compared to Step Functions. If you want to know how much your team could save annually, contact us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 2: Tight AWS Lock-In
&lt;/h2&gt;

&lt;p&gt;Locked into to one ecosystem? Facing downtime from a regional outage? That’s the reality with AWS Step Functions with everything depends on AWS-managed services. Unmeshed breaks that boundary, offering multi-cloud by design and running seamlessly across AWS, Azure, GCP or even on-prem environments. This ensures your workflows keep running even when a region or provider experiences downtime. Being flexible is critical for enterprise that demand resilience and control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 3: User/Developer-First Experience
&lt;/h2&gt;

&lt;p&gt;Unlike AWS Step Functions which require developers to write complex JSON definitions, Unmeshed built drag-and-drop workflow builder, YAML-based definitions, real-time debugging, tracing and more. New features are continuously added and updated to ensure users and developers spend less time to code and more time on business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 4: Not A Real-Time, Not An API-Driven Orchestration
&lt;/h2&gt;

&lt;p&gt;AWS Step Functions does not natively support true real-time and API-driven orchestration the way Unmeshed does. For more clarity, we list down some pain points from AWS Step Functions itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Latency per Step&lt;/strong&gt; - Each state transition in Step Functions adds measurable delay; on real-time or API-driven use cases such as chat or AI agent response come with high level of delay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing on Synchronous Flow&lt;/strong&gt; - Step Functions are built for event-driven and developer must bolt on API Gateway or Lambda wrappers to simulate a real-time flow, causing developers spending more time to monitor, instead of building features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Observability&lt;/strong&gt; - CloudWatch logs is designed to observe execution data after completion, developers can’t see step progress, partial outputs or triggers as they happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unmeshed solves this with built-in real-time orchestration with zero wait between steps. It provides unified support for both synchronous (request-response) and asynchronous (background) processes in one platform. Developers get to watch the live tracing and instant feedback loops with visual builder. Since it’s fully cloud-agnostic, it runs anywhere without dependency on AWS infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Are Teams Moving to Unmeshed?
&lt;/h2&gt;

&lt;p&gt;Unmeshed is built to modernize orchestration platform. By removing dependencies on AWS-specific services, Unmeshed delivers faster startup time, decreasing latency and greater resilience. If your team is scaling workflows across clouds or modernizing legacy orchestration, there’s never been a better time to move to Unmeshed.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>microservices</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Large Files Don't Belong in Your Workflow State</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Mon, 29 Jun 2026 09:51:15 +0000</pubDate>
      <link>https://dev.to/unmeshed/large-files-dont-belong-in-your-workflow-state-1cap</link>
      <guid>https://dev.to/unmeshed/large-files-dont-belong-in-your-workflow-state-1cap</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Large payloads do not always belong inside request bodies, step outputs, or execution state. When a process needs to work with Excel files, CSV exports, reports, or other bulky documents, it is usually better to store the file temporarily and let the workflow operate on the file path instead of pushing the full payload through every step.&lt;/p&gt;

&lt;p&gt;This approach keeps the process cleaner, reduces unnecessary payload movement, and makes file-heavy automation easier to manage.&lt;/p&gt;

&lt;p&gt;In this post, we will walk through an Unmeshed process that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads a file from a remote URL into mounted Unmeshed storage&lt;/li&gt;
&lt;li&gt;Reads and processes the file inside an Unmeshed Python Step&lt;/li&gt;
&lt;li&gt;Deletes the file after processing is complete&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Handle Large Payloads This Way
&lt;/h2&gt;

&lt;p&gt;For small JSON inputs, passing data directly between steps is simple. For large files, that pattern becomes inefficient.&lt;/p&gt;

&lt;p&gt;Common issues with large inline payloads include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bloated request or response sizes&lt;/li&gt;
&lt;li&gt;slower step-to-step data movement&lt;/li&gt;
&lt;li&gt;harder debugging when outputs become too large&lt;/li&gt;
&lt;li&gt;unnecessary memory pressure during execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using mounted storage gives you a better pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the file is downloaded once&lt;/li&gt;
&lt;li&gt;subsequent steps read it from disk&lt;/li&gt;
&lt;li&gt;only useful metadata and results are returned in step output&lt;/li&gt;
&lt;li&gt;the temporary file can be removed at the end of the process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Unmeshed, &lt;code&gt;/app/files&lt;/code&gt; is mounted to Unmeshed file storage. That makes it the correct location for temporary file-based processing inside a process execution.&lt;/p&gt;

&lt;p&gt;You can verify uploaded files from FileBrowser under &lt;strong&gt;Data and Assets&lt;/strong&gt; in Unmeshed. This is where files written to mounted storage can be viewed after they are uploaded by a process step.&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%2F5rvy29uxx8yg0zyidgf0.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%2F5rvy29uxx8yg0zyidgf0.png" alt="Unmeshed File Browser under Data &amp;amp; Assets, showing where files stored in mounted storage can be viewed and managed." width="202" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows &lt;strong&gt;File Browser&lt;/strong&gt; under &lt;strong&gt;Data &amp;amp; Assets&lt;/strong&gt;, where you can inspect files that have been uploaded to Unmeshed storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;Assume an upstream system provides an Excel file through a signed URL or file endpoint. The process needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fetch the file&lt;/li&gt;
&lt;li&gt;parse the spreadsheet&lt;/li&gt;
&lt;li&gt;generate a quick summary&lt;/li&gt;
&lt;li&gt;clean up the temporary copy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is exactly what the &lt;code&gt;large_payload_handling&lt;/code&gt; process does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Overview
&lt;/h2&gt;

&lt;p&gt;The process contains three Unmeshed Python Steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;temp_upload_to_unmeshed_storage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_records_and_process&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delete_file&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Download the File in an Unmeshed Python Step
&lt;/h2&gt;

&lt;p&gt;The first Unmeshed Python Step downloads a remote Excel file and stores it under &lt;code&gt;/app/files/myfiles/customFile.xlsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This matters because &lt;code&gt;/app/files&lt;/code&gt; is mounted to Unmeshed storage. If you save the file elsewhere, the next step may not be able to access it in the same expected way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;file_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://testing.s3.amazonaws.com/abcd/pqr/1234/myfile.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# /app/files is mounted to Unmeshed file storage
&lt;/span&gt;    &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/app/files/myfiles/customFile.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File downloaded and saved to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isSuccessful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Download failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isSuccessful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this Unmeshed Python Step does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;downloads the file as a stream instead of loading it fully into memory&lt;/li&gt;
&lt;li&gt;writes the content in chunks&lt;/li&gt;
&lt;li&gt;creates the target directory if it does not already exist&lt;/li&gt;
&lt;li&gt;returns a status message for execution visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Streaming is important here because it is a safer pattern for larger files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Read and Process the File in an Unmeshed Python Step
&lt;/h2&gt;

&lt;p&gt;Once the file is available in storage, the second Unmeshed Python Step opens it with &lt;code&gt;pandas&lt;/code&gt; and performs sample processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;file_to_process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/app/files/myfiles/customFile.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_to_process&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;row_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;column_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;numeric_summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;numeric_cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_dtypes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numeric_cols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;numeric_summary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;preview_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orient&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;records&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rowCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;columnCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;columns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;numericSummary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;numeric_summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;preview_data&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error processing file: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isSuccessful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this Unmeshed Python Step returns
&lt;/h3&gt;

&lt;p&gt;Instead of returning the full spreadsheet content, this step returns a compact and useful summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;total row count&lt;/li&gt;
&lt;li&gt;total column count&lt;/li&gt;
&lt;li&gt;list of columns&lt;/li&gt;
&lt;li&gt;numeric column summary&lt;/li&gt;
&lt;li&gt;preview of the first five rows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a much better output contract than passing the entire file content through the workflow state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Delete the Temporary File in an Unmeshed Python Step
&lt;/h2&gt;

&lt;p&gt;After processing is complete, the last Unmeshed Python Step removes the file from storage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/app/files/myfiles/customFile.xlsx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File deleted successfully&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File does not exist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isSuccessful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isSuccessful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cleaning up temporary files is a good operational habit. It helps prevent storage buildup when the process runs repeatedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  End-to-End Flow
&lt;/h2&gt;

&lt;p&gt;The full execution looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch the Excel file from a remote location&lt;/li&gt;
&lt;li&gt;Save it to &lt;code&gt;/app/files&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open it in an Unmeshed Python Step&lt;/li&gt;
&lt;li&gt;Extract useful summary data&lt;/li&gt;
&lt;li&gt;Delete the temporary file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern is simple, reliable, and practical for file-based workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Definition Summary
&lt;/h2&gt;

&lt;p&gt;Below is the same process expressed in documentation format for easy reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process Metadata
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;large_payload_handling&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Namespace:&lt;/strong&gt; &lt;code&gt;default&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;API_ORCHESTRATION&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step Definitions
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;code&gt;temp_upload_to_unmeshed_storage&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;PYTHON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; An Unmeshed Python Step that downloads a remote Excel file and stores it in Unmeshed-mounted storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input source:&lt;/strong&gt; Remote file URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; Status of file download&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;code&gt;read_records_and_process&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;PYTHON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; An Unmeshed Python Step that reads the Excel file and generates a compact summary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input source:&lt;/strong&gt; File stored at &lt;code&gt;/app/files/myfiles/customFile.xlsx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; Row count, column count, column names, numeric summary, and preview rows&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. &lt;code&gt;delete_file&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;PYTHON&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; An Unmeshed Python Step that deletes the temporary file after processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input source:&lt;/strong&gt; File path in mounted storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; Deletion status&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Full Process Definition
&lt;/h2&gt;

&lt;p&gt;In this process definition, the Python code is authored directly inside each Unmeshed &lt;code&gt;PYTHON&lt;/code&gt; step.&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;"orgId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"large_payload_handling"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"API_ORCHESTRATION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"steps"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"temp_upload_to_unmeshed_storage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PYTHON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"temp_upload_to_unmeshed_storage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Python code inside the Unmeshed step downloads the file from a remote URL and stores it under /app/files/myfiles/customFile.xlsx"&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;span class="p"&gt;},&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read_records_and_process"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PYTHON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read_records_and_process"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Python code inside the Unmeshed step reads the Excel file using pandas, computes summary information, and returns a compact preview"&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;span class="p"&gt;},&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delete_file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PYTHON"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delete_file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Python code inside the Unmeshed step deletes the temporary file from mounted Unmeshed storage"&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;span class="p"&gt;}&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;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;h1&gt;
  
  
  Best Practices for Large Payload Workflows
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;store large files in mounted storage instead of workflow state&lt;/li&gt;
&lt;li&gt;stream downloads when possible&lt;/li&gt;
&lt;li&gt;return summaries, not full file contents&lt;/li&gt;
&lt;li&gt;keep file paths predictable across steps&lt;/li&gt;
&lt;li&gt;always clean up temporary files after processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your workflow handles CSV files, PDFs, reports, or generated documents, this same pattern works well with only minor changes to the processing step.&lt;/p&gt;

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

&lt;p&gt;Large payload handling in Unmeshed is straightforward when you treat the file as a temporary resource rather than as step-to-step inline data.&lt;/p&gt;

&lt;p&gt;By combining mounted storage with Unmeshed Python Steps, you can build workflows that download, process, and clean up large files in a controlled and maintainable way.&lt;/p&gt;

</description>
      <category>python</category>
      <category>automation</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Telecom Order Fulfillment Becomes a Workflow Problem</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Thu, 25 Jun 2026 12:04:19 +0000</pubDate>
      <link>https://dev.to/unmeshed/why-telecom-order-fulfillment-becomes-a-workflow-problem-doo</link>
      <guid>https://dev.to/unmeshed/why-telecom-order-fulfillment-becomes-a-workflow-problem-doo</guid>
      <description>&lt;p&gt;The telecom industry has some of the most complex and distributed systems out there. Over time, business logic gets stitched together in whatever way makes sense at the time. Some parts become event-driven through pub/sub, some stay as direct API calls and state gets tracked across different databases.&lt;/p&gt;

&lt;p&gt;In a typical telecom environment, you are dealing with modern microservices, legacy OSS/BSS platforms, and third-party integrations. Each system owns a small part of the overall workflow. If you want a deeper dive into OSS/BSS fundamentals, Ericsson has a good reference.&lt;/p&gt;

&lt;p&gt;This setup works when things are simple. But once workflows become long-running, stateful, and spread across many systems, it becomes harder to manage. Durability gets questionable and scaling gets harder. Soon enough, no one has a clear end-to-end picture.&lt;/p&gt;

&lt;p&gt;Instead of getting into every telecom-specific detail, we will use an order fulfillment workflow to show how these pieces can be brought together into one coherent process. The goal is to show how Unmeshed can act as the orchestration layer that connects systems, keeping the workflow visible. While this example is based on telecom, the same business logic applies to any industry dealing with complex and distributed workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Requirements For Scalable Telecom Orchestration
&lt;/h2&gt;

&lt;p&gt;For this kind of workflow, the system needs to remember where each order is and be able to resume after failures. It also needs to avoid duplicate execution and show the status (completed, pending or blocked).&lt;/p&gt;

&lt;p&gt;With Unmeshed, independent steps like data fetches and validations can run in parallel. Teams can also build human-in-the-loop flows by pausing for approvals, routing tasks to the right people, and resuming the workflow without breaking the overall process. A mature orchestration platform should handle retries, timeouts, partial failures, and pause-and-resume behavior while preventing duplicate or conflicting execution through identifiers like order IDs.&lt;/p&gt;

&lt;p&gt;As the workload scales, teams spend less time worrying about performance and SLAs while still supporting both API-driven and event-driven workflows. They should also retain a complete audit trail of every action and decision across the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case: Designing an Order Fulfillment Workflow
&lt;/h2&gt;

&lt;p&gt;Telecom order fulfillment appears simple on the surface. A user selects a plan and chooses a device and places an order. In practice this initiates a multi-stage workflow that spans customer systems network provisioning inventory management billing and external integrations. Each stage introduces its own challenges and processes can run into failures latency-related issues and data dependencies which makes the workflow both distributed and stateful.&lt;/p&gt;

&lt;p&gt;Now there are a few ways you could build something like this.&lt;/p&gt;

&lt;p&gt;One approach is chaining API calls together. It starts with the frontend calling one service which calls another which calls another. It is simple but once you introduce things like waiting for instance giving the buyer a 24-hour waiting period while the cart remains open it starts to become awkward and increases the risk of partial or full failures. Eventually it gets messy, the state gets scattered across services and it becomes harder to know what is actually going on.&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%2Fp8zg39zn2u2ewt00zb3c.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%2Fp8zg39zn2u2ewt00zb3c.png" alt="Telecom order fulfillment built through chained API calls, where workflow state and business logic become distributed across multiple services." width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another approach is to rely heavily on event-driven systems where you publish events, let different services react and store state in databases.&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%2F9kc5a2h4f1jykjqp7yui.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%2F9kc5a2h4f1jykjqp7yui.png" alt="Event-driven telecom architecture where services communicate through events, improving scalability but making workflow visibility and debugging more difficult." width="799" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is more flexible and scalable but the downside is that your workflow logic is spread across multiple systems and teams. Because of the lack of visibility debugging becomes painful and something as simple as “where is this order stuck?” turns into a multi-hour investigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow in Action - Inside Unmeshed Platform
&lt;/h2&gt;

&lt;p&gt;Here, Unmeshed coordinates workflow, from the moment a user initiates an order. Instead of letting workflow logic live everywhere we model it as a Process Definition in Unmeshed. The first thing we do is wait for the cart to be finalized. This might sound trivial but it actually is not because we need to hold the state for potentially hours.&lt;/p&gt;

&lt;p&gt;In this workflow we model this as a Wait step with a pause of up to 24 hours. At times updates like adding a phone or changing a plan come in via APIs and update the same workflow instance. If the user fails to complete the purchase the workflow is either closed or a reminder email is sent. This is noticeably hard to do cleanly with just APIs or pub/sub.&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%2Fiv3fwq7koecjzkvrxuh5.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%2Fiv3fwq7koecjzkvrxuh5.png" alt="Telecom order fulfillment workflow orchestrated in Unmeshed, showing long-running state management, wait steps, and coordinated execution across distributed systems." width="799" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the user checks out that is where things get interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coordinate Parallel Work and Decision Table
&lt;/h2&gt;

&lt;p&gt;At this point a sequential workflow is not the most practical method because it increases the latency of the workflow. We model this using the Parallel step in Unmeshed where multiple independent steps can run in parallel such as fetching product details validating the plan pulling user data and running a credit check. Based on the output of all those steps we need to decide what to do next. For example, does this order require manager approval? Instead of hardcoding this logic we push it into the Decision Table so business rules can evolve without rewriting code.&lt;/p&gt;

&lt;p&gt;Once we know the approval level we bring in a Human-in-the-loop step. The workflow pauses and routes the task to the appropriate queue. If a manager cannot approve it they can escalate it to another approver and the workflow simply loops back and re-routes accordingly.&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%2F21s5hfavbl7devfov015.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%2F21s5hfavbl7devfov015.png" alt="Parallel execution, decision tables, and human approval routing inside a telecom order fulfillment workflow orchestrated with Unmeshed." width="800" height="929"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  From Approval to Fulfillment
&lt;/h2&gt;

&lt;p&gt;Now comes the non-trivial part of the entire workflow. We need the system to pause, resume and reroute without losing state or duplicating work. Once the approval is completed we move into fulfillment and this is where multiple backend systems come into play.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reserve inventory for the phone&lt;/li&gt;
&lt;li&gt;Create an order in a retail or fulfillment system&lt;/li&gt;
&lt;li&gt;Notify the store&lt;/li&gt;
&lt;li&gt;Update CRM and billing systems&lt;/li&gt;
&lt;li&gt;Trigger network provisioning to activate the line&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these is modeled as an HTTP step or integration step in Unmeshed. Failures happen in the real world and anything that could potentially happen probably will at some point, but we will not spend too much time explaining all of them here.&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%2Fv1tjy33bcryzi2chaduv.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%2Fv1tjy33bcryzi2chaduv.png" alt="Telecom fulfillment workflow progressing from approval to execution, coordinating inventory reservation, CRM updates, billing, store notifications, and network provisioning through Unmeshed." width="800" height="1445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Workflow Visibility Matters at Scale
&lt;/h2&gt;

&lt;p&gt;At a small scale almost anything works. As you scale anything can happen and everything breaks in interesting ways. Workflows run for hours or days, systems go down, traffic spikes happen and requirements change mid-flight.&lt;/p&gt;

&lt;p&gt;Without orchestration you usually end up handling retries, rollbacks and partial failures across multiple services yourself. With orchestration, all of these can be automated much more easily because they live in one place which is the workflow.&lt;/p&gt;

&lt;p&gt;Visibility matters at this point because it stops you from making wild guesses about how the system failed and frantically trying to locate where it failed. Every time this workflow runs Unmeshed keeps a full execution history. So if a client calls and asks “What happened to my order?” we could literally pull up the workflow using an order ID and see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which steps ran&lt;/li&gt;
&lt;li&gt;What data each step received&lt;/li&gt;
&lt;li&gt;Where it failed if it failed&lt;/li&gt;
&lt;li&gt;What decisions were made&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That level of visibility is almost impossible when logic is spread across systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing It Together
&lt;/h2&gt;

&lt;p&gt;Telecom order fulfillment is not just about connecting systems. At some point, it becomes about coordinating what happens across them.&lt;/p&gt;

&lt;p&gt;Once approvals, retries, failures, and long-running states come in, you need to know where the order is and what should happen next. That is the part orchestration helps with. Instead of spreading that logic across services, you keep the flow in one place and let each system do its own job.&lt;/p&gt;

&lt;p&gt;If you have workflows like this, try modeling one in Unmeshed and see whether it feels cleaner.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Automating Lead Qualification Without Glue Code</title>
      <dc:creator>The Unmeshed Team</dc:creator>
      <pubDate>Wed, 24 Jun 2026 10:08:44 +0000</pubDate>
      <link>https://dev.to/unmeshed/automating-lead-qualification-without-glue-code-1n45</link>
      <guid>https://dev.to/unmeshed/automating-lead-qualification-without-glue-code-1n45</guid>
      <description>&lt;h2&gt;
  
  
  Lead enrichment is a workflow problem
&lt;/h2&gt;

&lt;p&gt;Most signup systems start simple and then gradually accumulate logic around them. First you save the lead. Then you enrich the company domain. Then you verify whether the address is personal, disposable, or worth following up. Then someone asks for a Slack alert for promising signups. Before long, that "small" backend feature is spread across API handlers, background jobs, retry scripts, and a few hard-to-trace conditionals.&lt;/p&gt;

&lt;p&gt;That is exactly the kind of problem orchestration should own.&lt;/p&gt;

&lt;p&gt;This workflow shows how to keep the entire signup qualification path in one Unmeshed process while using Supabase Postgres as the system of record. The flow validates the incoming lead, stores it immediately, enriches the email domain with Hunter, verifies the mailbox with Kickbox, classifies the lead, routes high-value signups to Slack, and writes the enrichment result back to the same user record.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this workflow does
&lt;/h2&gt;

&lt;p&gt;The process definition is named &lt;code&gt;enrich_classify_and_route&lt;/code&gt;, and the shape is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signup payload
  -&amp;gt; validate_input
  -&amp;gt; postgres_insert_user
  -&amp;gt; http_hunter_domain_search
  -&amp;gt; http_kickbox_verify
  -&amp;gt; classify_lead
  -&amp;gt; switch_lead_route
      -&amp;gt; slack_message_high_value | exit_skip_slack_low_value
  -&amp;gt; postgres_update_user_enrichment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow follows a simple but important sequence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lead is written to Supabase before any external enrichment call runs.&lt;/li&gt;
&lt;li&gt;Hunter and Kickbox add context without turning the initial signup into a brittle all-or-nothing transaction.&lt;/li&gt;
&lt;li&gt;Slack only receives leads that pass the qualification rule.&lt;/li&gt;
&lt;li&gt;Supabase is updated at the end so the source-of-truth record reflects the outcome of the workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That sequencing is practical. If Hunter is slow or unavailable, you still have the signup stored safely. If Kickbox flags the email as free or disposable, the workflow records that information and exits the alerting path cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-step walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Validate and normalize the incoming lead
&lt;/h3&gt;

&lt;p&gt;The first JavaScript step, &lt;code&gt;validate_input&lt;/code&gt;, expects a payload with &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt;. It trims the values, lowercases the email, confirms the format is valid, and extracts the domain. If the payload is malformed, the workflow fails immediately with a clear error instead of writing incomplete data downstream.&lt;/p&gt;

&lt;p&gt;This is a small step, but it sets the tone for the whole process: every later step receives a predictable structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Insert the lead into Supabase
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;postgres_insert_user&lt;/code&gt; persists the lead with a simple SQL statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unmeshed binds the validated values directly from &lt;code&gt;validate_input&lt;/code&gt;, so the workflow writes a clean row before it asks any third-party service for more information. That design is useful in production because enrichment vendors can fail independently of your core signup path.&lt;/p&gt;

&lt;p&gt;Supabase fits naturally here because, for this workflow, it is standard PostgreSQL. Unmeshed connects through the Postgres integration and treats the &lt;code&gt;users&lt;/code&gt; table as the durable record of the lead.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Enrich the company context with Hunter
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;http_hunter_domain_search&lt;/code&gt; step calls Hunter's combined find API using the saved email address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.hunter.io/v2/combined/find?email={{steps.postgres_insert_user.output.results[0].email}}&amp;amp;api_key={{secrets.hunter_io_api_key}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step is marked optional, which is a thoughtful choice. Company enrichment is valuable, but it should not prevent the workflow from completing. If Hunter returns company data, the workflow can use it. If not, the process can still continue with the best information it has.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verify the mailbox with Kickbox
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;http_kickbox_verify&lt;/code&gt; step checks the same email with Kickbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.kickbox.com/v2/verify?email={{steps.postgres_insert_user.output.results[0].email}}&amp;amp;apikey={{secrets.kickbox_api_key}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important signal in this workflow is whether the address is free or disposable. That becomes the main input to qualification in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Classify the lead
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;classify_lead&lt;/code&gt; merges the outputs from validation, Hunter, and Kickbox into one normalized result object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;email
full_name
company
is_free_email
lead_type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current implementation uses a simple rule: if Kickbox reports &lt;code&gt;free === true&lt;/code&gt;, the lead is classified as &lt;code&gt;low_value&lt;/code&gt;; otherwise it becomes &lt;code&gt;high_value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is deliberately easy to understand and extend. Today, the workflow uses mailbox quality as the qualification gate. Tomorrow, the same step can incorporate company size, industry, geography, or CRM scoring without changing the outer structure of the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Route qualified leads to Slack
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;switch_lead_route&lt;/code&gt; step checks &lt;code&gt;classify_lead.output.result.lead_type&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;high_value -&amp;gt; slack_message_high_value
low_value  -&amp;gt; exit_skip_slack_low_value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That keeps notification logic out of application code. Sales or operations teams can trust that only leads meeting the workflow rule are pushed into Slack, and the message already includes the details that matter: name, email, and company.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Update the user record with enrichment results
&lt;/h3&gt;

&lt;p&gt;The final Postgres step writes the classification back to Supabase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;
  &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;is_free_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;is_free_email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;lead_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;lead_type&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This closes the loop neatly. The signup row starts with the basic identity fields, then the workflow appends the enrichment outcome once external checks are complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this design works well in practice
&lt;/h2&gt;

&lt;p&gt;There are plenty of ways to assemble this with controllers, queue workers, and custom scripts. The problem is not whether that approach can work. It is how long it stays understandable.&lt;/p&gt;

&lt;p&gt;With a single orchestration definition, teams get a few advantages immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The full lifecycle of a lead is visible in one place.&lt;/li&gt;
&lt;li&gt;Each step has explicit inputs, outputs, and execution history.&lt;/li&gt;
&lt;li&gt;Secrets for Hunter and Kickbox stay in workflow-managed configuration.&lt;/li&gt;
&lt;li&gt;Routing logic is easy to inspect and change without hunting through multiple services.&lt;/li&gt;
&lt;li&gt;Database writes and notifications become part of one traceable process instead of separate concerns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For teams running growth, onboarding, or outbound workflows, that visibility matters just as much as automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few implementation details worth noticing
&lt;/h2&gt;

&lt;p&gt;This workflow has several good design choices that are easy to miss on a first read:&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%2Fufqs4zecubkl91cfkoem.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%2Fufqs4zecubkl91cfkoem.png" alt="Implementation details and workflow design decisions for the lead enrichment workflow" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the kind of workflow that tends to grow with a product. Once the basic pipeline is working, most teams add CRM sync, deduplication, account assignment, welcome-email branching, or human review. Starting with an orchestration makes those additions much easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Natural next extensions
&lt;/h2&gt;

&lt;p&gt;The current version is already useful, but it is also a strong foundation for a more opinionated lead-ops pipeline. Common next steps include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add company-size or industry checks inside &lt;code&gt;classify_lead&lt;/code&gt; for more granular scoring.&lt;/li&gt;
&lt;li&gt;Write Hunter metadata such as domain confidence or organization details back to Supabase.&lt;/li&gt;
&lt;li&gt;Push high-value leads into a CRM in parallel with the Slack alert.&lt;/li&gt;
&lt;li&gt;Add retry policies or fallback behavior around third-party enrichment calls.&lt;/li&gt;
&lt;li&gt;Store workflow outcomes in a separate audit table for reporting and sales analytics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the workflow is already definition-driven, those changes stay additive instead of forcing a broader rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;The strongest part of this example is not that it uses Supabase, Hunter, Kickbox, or Slack. It is that the business process is explicit. A lead arrives, gets validated, gets stored, gets enriched, gets classified, and gets routed. Every step has a clear responsibility, and the resulting state is written back to the database your team already uses.&lt;/p&gt;

&lt;p&gt;That is what good orchestration looks like in practice: less hidden glue code, fewer scattered decisions, and a cleaner path from signup to follow-up.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>automation</category>
      <category>supabase</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
