Does Security Filter Pushdown work with LOOKUP() across tables, or only direct USEREMAIL() comparisons?

I have an AppSheet Core app on a Cloud SQL PostgreSQL backend, multi-tenant (multiple customers, each with multiple sub-accounts), with large tables (tens of thousands of rows per sub-account).

My Security Filter looks like this:

[account_id] = LOOKUP(USEREMAIL(), "User_Accounts", "email", "active_account")

After enabling Core, sync times didn’t improve (tested across multiple syncs to rule out cold cache).

Per the docs, pushdown works for “simple” filters like [Column] = USEREMAIL(), but for complex expressions “AppSheet converts whatever it can on the database and then the filter is (re)applied at the server.”

Questions:

  1. Does a LOOKUP() against another table disqualify pushdown entirely, or does it partially push down?
  2. Is there a recommended multi-tenant Security Filter pattern that stays pushdown-eligible (not User Settings — those aren’t secure for tenant isolation)?
  3. Would denormalizing a tenant/email column directly onto the large tables be the fix?

Thanks for any guidance — trying to decide whether Core helps here or if I need a different architecture.

A LOOKUP() is complex, so no “pushdown”.

The security filter expression is evaluated for each row of the table, so for each row of the table, the entire User_Accounts table is scanned.

For complex apps with user-specifics, you should be using something like this (props to @MultiTech ):

Your version would be based on your User_Accounts table (it seems). With Current_User in place, your security filter expression becomes:

[account_id] = ANY(Current_User[active_account])

Because Current_User has at most one row, the operation is trivial, versus the scan of the entire User_Accounts table.

Aside from that, you need to check all of your formulas and virtual columns too. This will make your sync time faster, and the security filter is the next step.

Thanks a lot. I used a performance analyzer on AppSheet and found out that 2 virtual columns were doing nonsense calculations. app was taking around a minute to sync before. now takes 2 seconds.

You were right! thanks

Amazing!!!

@Julián_Flórez, please help me marking the post as a solution! This will help others to find a fix to their problem whenever they face a similar issue.

Done!