Heuristic:Treeverse LakeFS Action Cache Wait Tip
| Knowledge Sources | |
|---|---|
| Domains | Debugging, Hooks |
| Last Updated | 2026-02-08 10:00 GMT |
Overview
After uploading action hook YAML files, you must wait at least 8 seconds for the actions cache to expire before the hooks take effect.
Description
lakeFS caches action definitions with a TTL of 20 seconds and a 3-second jitter. When you upload or modify action YAML files in the `_lakefs_actions/` namespace, the server will not recognize the changes until the cache entry expires. The integration test suite uses a hardcoded 8-second wait as a reliable delay to ensure cache expiration. Failing to wait results in hooks silently not triggering, which is a common source of confusion.
Usage
Use this heuristic whenever you are programmatically uploading or updating action hook YAML files and need the hooks to be active for a subsequent commit or merge operation. This applies to any workflow that dynamically deploys hooks (WF3: Write Audit Publish With Hooks).
The Insight (Rule of Thumb)
- Action: After uploading action files to `_lakefs_actions/`, insert a delay before performing a commit or merge.
- Value: Wait at least 8 seconds (matching the test suite constant).
- Trade-off: Adds latency to automated hook deployment workflows. Alternatively, configure shorter cache TTL via `auth.cache.ttl` if acceptable.
- Why not wait 20 seconds? The 20-second TTL is the maximum. With 3-second jitter, most cache entries expire well before 20 seconds. The 8-second wait provides a reliable safety margin.
Reasoning
The lakeFS server caches action definitions to avoid reading them from the blockstore on every commit/merge event. The cache configuration (`auth.cache.ttl=20s`, `auth.cache.jitter=3s`) means entries expire between 17 and 23 seconds. However, the cache is populated on first access, so the actual wait depends on when the cache was last populated. The 8-second constant in the test suite was empirically determined to be sufficient for reliable test execution while minimizing test runtime.
Code Evidence
Cache wait function from `esti/hooks.go:642-651`:
func WaitForCacheExpiration(ctx context.Context, t *testing.T) {
t.Helper()
t.Log("Wait for actions cache to expire")
const cacheExpireTime = 8 * time.Second
select {
case <-ctx.Done():
return
case <-time.After(cacheExpireTime):
}
}
Usage after uploading actions from `esti/hooks.go:675-680`:
// Upload action YAML files to _lakefs_actions/ prefix
resp, err := UploadContent(ctx, repo, branch, path.Join("_lakefs_actions", ent), action, lakeFSClient)
require.NoError(t, err)
require.Equal(t, http.StatusCreated, resp.StatusCode())
// ... after all files uploaded:
WaitForCacheExpiration(ctx, t)
Cache TTL configuration from `pkg/config/defaults.go:66-69`:
viper.SetDefault("auth.cache.enabled", true)
viper.SetDefault("auth.cache.size", 1024)
viper.SetDefault("auth.cache.ttl", 20*time.Second)
viper.SetDefault("auth.cache.jitter", 3*time.Second)