Optimizing Tines Stories - Tips and Tricks for Building Efficiently

Written by Colleen GallagherCustomer Success Engineer, Tines

Published on September 30, 2024

The goal of Tines is to efficiently automate processes while ensuring that the resulting workflows (also known as stories) are easy for users to understand, regardless of their background in Tines or coding knowledge. When trying to answer the question, “How can I best optimize my Tines stories?”, the answer is: it depends.

Achieving this goal requires a balance of reducing the number of actions, ensuring the story runs quickly, and keeping it easy to maintain. This balance can vary based on your needs and priorities across your team or company. The key areas in regards to optimization are building efficiently, error handling, maintainability (or readability), and continuous improvement. In part II of this blog post series, I'll focus on tips and tricks for managing stories efficiently, but here, I’ll share tips, tricks and examples to enable more efficient building.

Best practices for building efficiently 

The best way to optimize a story is to modularize and condense wherever possible. This reduces the total number of actions in a story, decreases story run time, and can be easier to maintain. Although the storyboard is expansive, it is best practice to reduce the overall number of actions in a story.

1. Send to story 

Send to Story” is a helpful feature that allows for building in a modular way and reduces the total events in a given story. If you have a series of actions that may be useful to other stories, you can use this feature to call that story from a different story with a given input, execute those actions in a separate story, and return the output to the original story. Some examples could include sending an IP or domain to Recorded Future to get enriched or exporting a story to Github.

Cutting down the length of a story run can help, especially for stories that need to run multiple times a day. The best option for stories that are complex and take a lot of time to run through is to break up the story into modular “send to stories”. This means that a loop in a story doesn’t get called 1,000 times, instead there are 1,000 separate “send to story” runs, which also makes it more readable and easier to troubleshoot.

Lastly, this feature is useful when it comes to maintainability as it is one source of truth, instead of having to update all occurrences of the same logic or group of actions.

2. Trigger actions 

Triggers are great when you need to add conditional logic to your stories and decide when different flows of actions need to take place. When starting out, it may be easier to include a separate trigger action to represent each decision branch in your story for readability, but as the number of branches increase, it's better to condense the total number of triggers. When a story has a lot of triggers to process at the start of a branch, this starts to impact the length and total number of events in a story run. As we move to optimize a story, reducing triggers can be an easy way to increase efficiency in a story.

Triggers have the “no match” option so if a rule does not match, the event data can kick off a separate branch without the need for an additional trigger.

There is also an option to “emit no match” which will emit an event if no match is found against the rules within a trigger. This keeps the story flowing downstream if you want to determine if a certain value fits a rule, but you don't want a separate branch, nor do you want the story to stop.

You can leverage “must match” as an additional option with as many rules as needed. There is no enforced limit on number of rules within a trigger, but actions may start to lose efficiency when it reaches about 100.

Another trick is to condense trigger branches by leveraging “must match = 1” in combination with multiple rules, essentially using OR. For example, if a trigger is checking for a particular value, but each branch has similar downstream actions depending on that value, you can combine those branches into one and reference the output of that trigger for those actions.

Example Story

How to optimize Tines Stories

Optimize existing Tines stories using some of these techniques for increased efficiency and performance.

Created by

Colleen Gallagher

Note: By default, multiple rules in a trigger are interpreted using AND logic.

3. Action options 

Options unlock additional value with how we configure our actions. Each action has a variety of options that we can add in. Let’s take a look at a few ways to leverage this.

Local values

Nesting or combining functions within an action or leveraging local values can also cut down on total number of actions needed in a story. Local values are upfront calculations that can be referenced within the action using LOCAL. There's a trade-off between condensing the logic and the number of actions and the more readability and ability to understand a given story. We'll talk more about this in the next blog.

Customize output

A newer feature that we've added to HTTP request actions is “customize output”. This helps condense logic into fewer actions by removing the need to parse data in a separate event transform action. All can be done in one action.

4. Webhook filtering 

A newer feature that has been added to Webhook action is the ability to filter events based on specific rules, similar to trigger actions. This prevents an event from being generated from a given webhook if it does not match the specified rules. This can help cut down on noisy workflows, for example, SIEM alerts, without having to use a trigger action downstream, thus still creating events before filtering them out. This instead stops data at the start that does not need to be processed in the story.

5. Event transform actions 

There are various modes within event transform actions that can be leveraged for different types of data transformations and adding robustness to a given story.

Mode: explode and implode

Data structures such as arrays and objects will be the most common type that you will be dealing with in your Tines stories. There are various approaches to handling these types of data and each approach varies depending on the workflow you are building out. Actions such as explode and implode coupled together can be helpful for data that needs to be processed separately or needs to be emitted as its own event for an HTTP request. For example, starting with an array of IPs that need to be separately analyzed within their own API calls. This is where explode and implode can be helpful. You can also use explodes in conjunction with triggers to filter out data within an array or object.

If building a story to allow for multiple processes to run in parallel, implode can be used as a counter to collect all the events generated from those separate processes. The trick is to add an event transform action after each process with the same name so each path is the same for the implode to catch and set the size of the implode to the number of branches (or processes).

Mode: message + Tines formulas

For cases where you just need to filter out data or apply logic to all elements within an object or an array, using Tines functions is a better method.

Instead of exploding data within an array or object and using triggers, there are other methods of looping through the values and applying logic to each. One of those is utilizing the “loop” functionality within an event transform action in “message-only” mode in combination with Tines functions. Another method is the use of WHERE() or LAMBDA() functions, such as FILTER(), REJECT(), MAP_LAMBDA() and FIND() that execute the looping of data at the function level instead of the action level. Use FILTER() if there is complex logic to be applied, but if the logic is flat (ie field = value), WHERE() is more performant.

Note: For looping through data that requires a string output only, like a Slack message, email or a Jira ticket, tags can be used.

Tags are generally used for string or text output (for things like emails or tickets) whereas the IF() function can also be used for text output, but usually its better for nesting additional functions and logic or displaying other data types when conditions are met.

Some things to note about both approaches that may influence using one over the other:

  • When using tags, you cannot modify the field mode from text (the little “A” to the right of your field in a pa