Performance vs. Freshness – Mastering a!refreshVariable

If you’ve been building in Appian for a while, you know the struggle: you update a record, navigate back to your dashboard, and… nothing. The old data is still staring you in the face.

On the flip side, we’ve all seen interfaces that feel “heavy” or laggy because they’re re-running expensive queries every time a user clicks a checkbox.

The secret to fixing both is mastering a!refreshVariable.

The Default: Appian is Lazy (And That’s Good)

By default, a!localVariables caches values. If a variable doesn’t depend on another variable that changed, Appian won’t re-evaluate it. This is great for performance, but it’s the primary reason your data feels “stuck.”

When you wrap a variable in a!refreshVariable(), you’re essentially taking the steering wheel away from Appian’s default caching engine.

The “Refresh” Toolkit

There are four main levers you can pull to control when your data updates. Let’s break down when to use which.

refreshOnReferencedVarChange (The “Smart” Default)

By default, this is true. If your query depends on local!searchQuery, Appian refreshes it when that search term changes.

Pro Tip: Set this to false if you want to let a user tweak multiple filters and only refresh the data when they hit a “Search” button.

refreshOnVarChange

This is your manual override. You can pass a single variable or a list of variables here.

Best Use Case: Refreshing data after a “Delete” or “Update” action that doesn’t natively change the query parameters.

Example: Use a local!refreshCounter that increments every time a record action completes.

refreshInterval

This is the “Dashboard” setting. It accepts values in minutes (minimum 0.5).

Warning: Do not use this unless you absolutely have to. If you have 50 users on a site with a 30-second refresh interval, you are hitting your database 100 times every minute, even if they’re just staring at the screen.

refreshAlways

The “Nuclear” option. If set to true, this variable re-evaluates on every single user interaction—even if they’re just clicking a tab or typing in a text box.

When to use: Almost never for queries. Use it for UI logic that needs to be hyper-reactive.

Intentional Caching: The Performance Gain

We usually talk about how to force a refresh, but a!refreshVariable is also your best tool for intentional caching.

If you have a heavy query that fetches a list of constants or static metadata, you can set refreshOnReferencedVarChange: false. This ensures that even if the rest of the interface is busy re-evaluating, that specific heavy data stays put in the cache for the duration of the user’s session.

local!staticMetadata: a!refreshVariable(
value: rule!GET_heavyMetadata(),
refreshOnReferencedVarChange: false /* Keeps it cached no matter what */
)

The “Gotcha”: Nested Rules

The most common mistake I see? Putting a!refreshVariable inside a child rule but expecting the parent interface to control it.

If your data-fetching logic is inside a rule, keep the rule “dumb” (just a standard expression) and wrap the calling of that rule in a!refreshVariable at the interface level. This keeps your refresh logic centralized and much easier to debug.

Summary

  • Need it live? refreshOnVarChange is your best friend.
  • Need it fast? Use refreshOnReferencedVarChange: false to lock down static data.
  • Building a TV Dashboard? Only then should you touch refreshInterval.
  • If data changes in the background, refreshAlways might be the only way.

Do only query data if needed, only as much as needed, and refresh only when needed!

Keep rocking!

2 thoughts on “Performance vs. Freshness – Mastering a!refreshVariable

  1. Thank you Stefan, this is a function that can lead us to antipatterns really easy (I’m guilty). I liked the pattern for cached fetched data. I will try to implement it from now on.

Leave a Reply