Files
twenty/packages
Clive F f2e3eb5fb7 perf(twenty-server): browser-cache picture file responses (avatars/logos) (#22166)
Fixes #22163.

## Why

Picture file responses (`GET /file/:fileFolder/:id`,
`FileController.getFileById`)
set no `Cache-Control` header, so the browser re-fetches the same
avatar/picture
on every render. When one member's avatar appears many times on a page
(e.g. a
record table or Kanban where that member owns many rows), this fires
dozens of
parallel GETs for the identical image; the browser cancels the redundant
in-flight ones, and the server logs each client-aborted stream as
`Error streaming file from storage`.

Picture files are content-addressed by an immutable file id — changing
an avatar
or logo mints a new file id (and therefore a new URL) — so the bytes at
any given
URL never change and can be cached aggressively.

## What

- `setFileResponseHeaders` now adds
`Cache-Control: private, max-age=86400, immutable` for the picture
folders
  (`CorePicture`, `ProfilePicture`, `WorkspaceLogo`, `PersonPicture`);
  `getFileById` passes the `fileFolder` through.
- Scoped to picture folders so non-image files (attachments, tarballs,
source, …)
  are not cached past a permission/visibility change.
- `private` because files are served behind a per-workspace file token;
`immutable` + the content-addressed id gives automatic cache-busting
when the
  picture changes.

## Tests

- Unit tests for `setFileResponseHeaders`: header is set for each
picture folder,
  and not set for non-picture folders or when no folder is provided.
- Controller test asserts the header on a `CorePicture` stream response.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22166?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-07-03 11:43:36 +02:00
..