You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/blog/posts/2026-05-29_unblocking_apps_performance_bottleneck/main.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,29 +15,29 @@ For a while now there was a problem with the Immich app. On the web it did not s
15
15
16
16
## How requests travel inside a Shard
17
17
18
-
Every request that hits a shard goes through Traefik first. It is then decided whether that request may pass on to the app or is blocked. All requests from paired devices may pass on as well as requests that target a public endpoint. This is decided by the shard core application. And that means every request gets forwarded by Traefik to that application where the decision needs to happen.
18
+
Every request that hits a shard goes through Traefik first. It is then decided whether that request may pass on to the app or is blocked. All requests from paired devices may pass on as well as requests that target a public endpoint. This is decided by the shard core application. And that means every request gets forwarded by Traefik to that application where the decision needs to happen. It is like a bouncer who has to check your ID for every single sip of your drink, not just once at the door.
19
19
20
20
In order to make that decision, the shard core needs to query a few bits of information. What kind of app is targeted? How is its permission model configured? What device is requesting access? This is all in the database, so the database needs to be queried. And to query the database, a database connection is required. This connection is not created each time, but pulled from a pool of connections that are standing by and can be used and then returned to the pool.
21
21
22
22
```mermaid
23
23
flowchart TD
24
24
Browser([Paired browser])
25
25
Traefik[Traefik]
26
-
ShardCore[shard_core<br/>/internal/auth]
27
-
DB[(Postgres)]
28
-
App[App container<br/>e.g. Actual Budget]
26
+
ShardCore[Shard Core<br/>/internal/auth]
27
+
DB[(Database)]
28
+
App[App<br/>e.g. Immich]
29
29
30
30
Browser -->|HTTPS request| Traefik
31
31
Traefik -->|forwardAuth| ShardCore
32
32
ShardCore -->|find app + identity| DB
33
-
ShardCore -->|200 / 401| Traefik
34
-
Traefik -->|forward on 200| App
33
+
ShardCore -->|allow/block| Traefik
34
+
Traefik -->|forward| App
35
35
App -->|response| Browser
36
36
```
37
37
38
38
## The Bottleneck
39
39
40
-
As it turned out, each single request pulled two connections from the pool to answer the question of whether it is allowed or must be blocked. Also the pool had only four connections available at a time. This is the default setting and I never questioned it, I did not even consciously see it. But when an app opens 30 or 40 requests on its first start, only the first two can be served right away. All the others are waiting for database connections to be returned and then given out again. A whole bunch of requests block for a long time.
40
+
As it turned out, each single request pulled two connections from the pool to answer the question of whether it is allowed or must be blocked. Also the pool had only four connections available at a time. This is the default setting and I never questioned it, I did not even consciously see it. But when an app opens 30 or 40 requests on its first start, only the first two can be served right away. All the others are waiting for database connections to be returned and then given out again. A whole bunch of requests block for a long time. The crowd piles up behind the rope while the bouncer works through them two at a time.
41
41
42
42
In fact, for apps like Immich or Actual, which open lots of connections during their startup, the long tail of piled-up and waiting requests frequently hit the 45-second browser timeout and the app fails to load at all.
0 commit comments