tripit: dedicated 100/1000 rate-limit — photo grid 429s on the default 10/50
Some checks failed
ci/woodpecker/push/build-cli Pipeline was canceled
ci/woodpecker/push/default Pipeline was canceled

Viktor hit a wall of 429s scrolling the new trip Photos tab: every Immich
thumbnail proxies through tripit's /api, so a few-hundred-photo trip is
that many parallel GETs from one IP — far past the shared Traefik
limiter's average 10 / burst 50. Fourth instance of the parallel-asset
pattern (ha-sofia, ActualBudget, noVNC); same cure: dedicated
tripit-rate-limit middleware (average 100, burst 1000) +
skip_default_rate_limit on the main tripit ingress only. The token-gated
calendar/email/slack carve-outs keep the strict default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-06-12 19:15:56 +00:00
parent e8a4eb0f05
commit eef4dc7f63
2 changed files with 31 additions and 0 deletions

View file

@ -319,6 +319,31 @@ resource "kubernetes_manifest" "middleware_actualbudget_rate_limit" {
depends_on = [helm_release.traefik]
}
# TripIt-specific rate limit. The trip Photos tab proxies every Immich
# thumbnail through tripit's own /api scrolling a few-hundred-photo trip
# fires that many parallel image GETs from one client IP, and the default
# 10/50 limiter 429s the tail (fourth instance of the parallel-asset
# pattern, after ha-sofia, ActualBudget, and noVNC). Burst must absorb a
# full trip-gallery scroll plus lightbox prefetches.
resource "kubernetes_manifest" "middleware_tripit_rate_limit" {
manifest = {
apiVersion = "traefik.io/v1alpha1"
kind = "Middleware"
metadata = {
name = "tripit-rate-limit"
namespace = kubernetes_namespace.traefik.metadata[0].name
}
spec = {
rateLimit = {
average = 100
burst = 1000
}
}
}
depends_on = [helm_release.traefik]
}
# Compress responses to clients at the entrypoint level (outermost).
# Applied at websecure entrypoint so all responses get compressed.
# Uses includedContentTypes (whitelist) instead of excludedContentTypes:

View file

@ -760,6 +760,12 @@ module "ingress" {
name = "tripit"
port = 8080
tls_secret_name = var.tls_secret_name
# The Photos tab proxies Immich thumbnails through /api a trip-gallery
# scroll is hundreds of parallel image GETs, far past the default 10/50
# limiter. Dedicated 100/1000 middleware (stacks/traefik middleware.tf);
# the calendar/email carve-out ingresses below stay on the default.
skip_default_rate_limit = true
extra_middlewares = ["traefik-tripit-rate-limit@kubernetescrd"]
}
# Calendar feed carve-out for the same host: path /api/calendar served by the