Back to Blog
Escaping SaaS Lock-in: Automating Workflows with self-hosted `automatisch`
8 min readJul 4, 20262 views

Escaping SaaS Lock-in: Automating Workflows with self-hosted `automatisch`

I've used my fair share of SaaS workflow automation tools, and they're great until the costs skyrocket or a niche integration is missing. automatish offers a refreshing, self-hosted alternative.

AutomationFull-StackToolingDistributed Systems
Share

by Sunil Band

The Hidden Costs of Cloud Workflow Automation

We all love workflow automation. Whether it's connecting a new Slack message to a Jira ticket, syncing customer data across CRMs, or triggering a build when a new file hits S3, these tools are indispensable for modern businesses. The problem is, for all their power, the popular SaaS options like Zapier or Make (formerly Integromat) often come with hidden costs and limitations that start to pinch as you scale. You hit rate limits, the per-task pricing gets exorbitant, or you find yourself needing a very specific integration that doesn't exist.

I've been looking for a robust, self-hostable alternative that offers the same visual builder experience without the vendor lock-in and escalating costs. Most open-source solutions feel like a step backward in UX, or they're more developer-focused and lack the ease of use for non-technical team members. This is where automatisch caught my eye.

Why Self-Host Your Automation?

Before diving into how automatisch works, let's talk about why you'd even consider self-hosting your mission-critical automations. It's not just about cost, though that's a huge factor for many. It's also about data sovereignty, customization, and control.

When your automations run on a third-party service, your data flows through their infrastructure. For sensitive internal tools or B2B applications, this can be a non-starter due to compliance or security concerns. Self-hosting means your data stays within your controlled environment. Furthermore, while SaaS platforms offer many integrations, there's always a long tail of internal tools or very specific APIs that they don't support. With a self-hostable solution, you have the freedom to build any custom integration you need, exactly how you need it, without waiting for a vendor to support it.

automatisch provides a visual drag-and-drop interface similar to its commercial counterparts, but it runs wherever you deploy it. This gives you the best of both worlds: ease of use for creating complex workflows and the ultimate flexibility and control over your data and infrastructure. It's built on a modern stack with TypeScript, React, and Go, ensuring it's maintainable and performant.

Building Your First Workflow: From Webhook to Slack

Let's walk through a simple, yet powerful, example: setting up a workflow that listens for a webhook and then sends a message to a Slack channel. This is a common pattern for integrating services that don't have direct integrations or for custom event handling.

First, you'll need automatisch up and running. The easiest way to get started is with Docker:

bash
docker run -d -p 3000:3000 automatisch/automatisch:latest

Once it's running, navigate to http://localhost:3000 in your browser. You'll be prompted to set up an admin account. After that, you're ready to create your first workflow.

Step 1: Create a new Workflow

From the dashboard, click "Create new workflow". You'll be presented with a blank canvas. The core concept is connecting nodes, which represent actions or triggers, with edges that define the flow of data.

Step 2: Add a Webhook Trigger

We need a way to kick off our workflow. Search for "Webhook" in the node palette and drag it onto the canvas. Double-click the "Webhook" node to configure it. automatisch will automatically generate a unique URL for this webhook. This is the URL you'll use in external services to trigger this specific workflow.

For example, let's say we want to trigger this when a new user signs up in a custom application. Your application would make a POST request to this URL with the user data in the body.

typescript
// Example of how your external app might trigger the webhook
async function triggerNewUserWebhook(userData: { name: string; email: string }) {
  try {
    const webhookUrl = 'YOUR_AUTOMATISCH_WEBHOOK_URL'; // Replace with the actual URL from the node
    const response = await fetch(webhookUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(userData),
    });

    if (!response.ok) {
      console.error('Failed to trigger webhook:', response.statusText);
    }
    console.log('Webhook triggered successfully!');
  } catch (error) {
    console.error('Error triggering webhook:', error);
  }
}

// Example usage:
triggerNewUserWebhook({ name: 'Alice', email: 'alice@example.com' });

Step 3: Add a Slack Message Node

Now we need to send a message to Slack. Search for "Slack" and drag the "Send Message" node onto the canvas. Connect the output of the "Webhook" node to the input of the "Slack Send Message" node.

Double-click the Slack node to configure it. You'll need to provide your Slack Webhook URL. This is different from the automatisch webhook. You can get a Slack incoming webhook URL by creating a new Slack app or going to https://api.slack.com/apps.

For the message content, automatisch uses expressions to access data from previous nodes. Since our webhook will receive userData, we can access it using {{ $node.Webhook.json.name }} and {{ $node.Webhook.json.email }}. The structure of $node.Webhook.json depends on the JSON payload your webhook receives.

Configure the message like this:

  • Channel: #general (or any channel you want)
  • Text: New user signed up: {{ $node.Webhook.json.name }} ({{ $node.Webhook.json.email }})

This expression syntax is crucial for making dynamic workflows. You can inspect the output of any node by running the workflow once (even with dummy data in the webhook) and checking the "Executions" tab.

Step 4: Test and Activate

Save your workflow. Before activating, you can test it by clicking the "Test workflow" button and providing sample JSON data for the webhook payload. This allows you to quickly iterate and ensure your expressions are correct and the Slack message is formatted as expected.

Once satisfied, toggle the workflow to "Active". Now, any POST request to your webhook URL will trigger the Slack message.

Beyond the Basics: Features and Power

This simple example barely scratches the surface of what automatisch can do. Here are some other powerful features:

  • Conditional Logic: Add If nodes to branch your workflows based on data. For example, send a different Slack message if the user's email domain is a specific one.
  • Looping: Process lists of items using For Each nodes, iterating through an array received from an API or database query.
  • Custom Code: For scenarios where the existing nodes aren't enough, you can write JavaScript code directly within a Code node. This is a game-changer for complex data transformations or interacting with custom internal APIs. The code node provides access to the data from previous nodes, allowing you to manipulate it before passing it to the next step.
javascript
    // Example of a Code node to transform data
    // Input data from a previous node, e.g., an array of user objects
    const users = $node.FetchUsers.json.data; // Assuming 'FetchUsers' is a previous node fetching user data

    // Transform each user object
    const transformedUsers = users.map(user => ({
      fullName: `${user.firstName} ${user.lastName}`,
      emailAddress: user.email,
      isActive: user.status === 'active'
    }));

    // Output the transformed data to the next node
    return { transformedUsers };
  • Error Handling: Configure what happens when a node fails. You can retry, send a notification, or divert the workflow to an error-specific path.
  • Many Integrations: While you can build your own, automatisch comes with a growing list of built-in integrations for databases (Postgres, MySQL, MongoDB), messaging services (Slack, Discord), cloud services (AWS S3), and more. If a connector doesn't exist, the HTTP Request node can connect to virtually any REST API.
  • API: automatisch exposes an API, allowing you to programmatically manage workflows, execute them, and retrieve execution logs. This is particularly useful for embedding automation capabilities within your own applications or for CI/CD pipelines.

Trade-offs and Considerations

While automatisch is a powerful tool, it's not a silver bullet. Self-hosting always comes with responsibilities:

  • Maintenance: You're responsible for updates, backups, and ensuring the underlying infrastructure (Docker, Kubernetes, VM) is healthy. This isn't a set-it-and-forget-it solution like a SaaS platform.
  • Scalability: While automatisch can scale, you'll need to manage the scaling of your Docker containers or Kubernetes pods yourself if you have very high throughput requirements. This is where cloud providers handle a lot of the heavy lifting for SaaS.
  • Monitoring: You'll need to set up your own monitoring and alerting for the automatisch instance and its underlying database. The built-in execution logs are great for debugging individual workflows, but you'll want broader system-level monitoring.

For smaller teams or projects with limited DevOps resources, the convenience of a fully managed SaaS might still outweigh the benefits of self-hosting. However, for those with the technical chops and a desire for ultimate control and cost optimization, automatisch is a compelling option.

Wrapping up

automatisch is a mature, open-source workflow automation platform that gives you the power of commercial solutions without the vendor lock-in. Its visual builder makes complex orchestrations manageable, and its extensibility with custom code nodes means you're rarely truly stuck. If you're tired of escalating SaaS bills or hitting integration walls, it's definitely worth a look.

My suggestion: clone the automatisch repository, get it running with Docker Compose locally, and try to recreate one of your existing Zapier or Make workflows. You'll quickly get a feel for its capabilities and whether it fits your team's needs.

More from the blog
Available for projectsReady to make something fun 🎈

Ready to build the next system?Wanna build something awesome together?

Currently accepting high-impact opportunities in frontend engineering and scalable web applications.Got a cool idea rattling around? Let's grab a virtual coffee and turn it into something people love. ☕