Tink.ex uses Cachex (v4.1+) for transparent response caching. Caching is on by default and dramatically reduces API calls for slow-changing resources.

Configuration

# config/config.exs
config :tink,
  cache: [
    enabled:  true,     # Set to false to disable globally
    max_size: 1_000     # Max number of entries in the cache
  ]

Disabling in tests

# config/test.exs
config :tink,
  cache: [enabled: false]

Bypassing per-client

Set cache: false on a client to skip caching for all calls on that client:

client_no_cache = %{user_client | cache: false}
{:ok, accounts} = Tink.Accounts.list(client_no_cache)

TTLs by resource type

TTL keyDurationUsed for
:categories24 hoursEnrichment PFM categories
:providers2 hoursProvider lists and details
:statistics1 hourStatistics query results
:default5 minutesAccounts, investments, loans, budgets
:balances1 minuteAccount balances
:credentials30 secondsCredential status

Cache key pattern

Keys follow "token_prefix:resource:identifier":

  • "abc12345:accounts:123" — single account for a user
  • "abc12345:budgets" — budget list for a user
  • "global:categories:en_US" — categories (not user-scoped)
  • "global:providers:GB" — providers for a market

The token_prefix is the first 12 characters of the access token. This scopes entries per user session without storing PII as cache keys.

Write invalidation

All write operations automatically invalidate the relevant cache entries:

# This invalidates both the individual account cache and the list cache
{:ok, updated} = Tink.Accounts.update(client, account_id, %{"name" => "New name"})

# Budget deletion invalidates both the specific budget and the list
:ok = Tink.Budgets.delete(client, budget_id)

Manual invalidation

# Delete a specific key
Tink.Cache.delete("abc12345:accounts:account-001")

# Invalidate all entries for a user (e.g. after full refresh)
Tink.Cache.invalidate_user("abc12345")

# Invalidate by prefix
Tink.Cache.invalidate_prefix("abc12345:budgets")

# Check stats
{:ok, stats} = Tink.Cache.stats()

Telemetry

Cache events:

EventMetadata
[:tink, :cache, :hit]%{key: cache_key}
[:tink, :cache, :miss]%{key: cache_key}
:telemetry.attach("tink-cache", [:tink, :cache, :miss], fn _event, _measurements, meta, _config ->
  Logger.debug("Cache miss: #{meta.key}")
end, nil)