Skip to content

perf: optimize Heroku deployment speed #189

@ericfitz

Description

@ericfitz

Summary

Heroku deployments are slow. Investigation identified several contributing factors related to unnecessary files in the slug, unused dependencies being compiled, and lack of build optimizations.

Analysis

The current deployment (git push heroku main) uses the heroku/go buildpack. Every push uploads all 795 tracked files (14MB), downloads ~100+ Go dependencies, and compiles the full binary including drivers that are never used on Heroku.

Root Causes

Issue Impact Effort
No .slugignore file High Low
Unused DB drivers compiled (MySQL, SQLServer, SQLite) Medium Medium
AWS SDK pulled in unconditionally Medium Medium
No GO_INSTALL_FLAGS config var set Low-Medium Low
quic-go transitive dependency overhead Low Medium

Details

1. Missing .slugignore (HIGH IMPACT, LOW EFFORT)

Without .slugignore, Heroku processes all tracked files including test/ (67 files), docs/ (95 files), terraform/ (64 files), wstest/, scripts/, static/ (PNG images), api-schema/, .github/, and .claude/. None of these are needed for compilation.

2. Unused DB drivers (MEDIUM IMPACT, MEDIUM EFFORT)

go.mod includes gorm.io/driver/mysql, gorm.io/driver/sqlserver, and gorm.io/driver/sqlite as direct dependencies. Heroku only uses PostgreSQL. Oracle is already gated behind build tags (gorm_oracle.go / gorm_no_oracle.go), but these three are unconditionally imported. Even with CGO_ENABLED=0, the compiler still processes them.

3. AWS SDK v2 (MEDIUM IMPACT, MEDIUM EFFORT)

The AWS SDK v2 pulls in ~12 modules for secrets management. If Heroku uses config vars for secrets instead of AWS Secrets Manager, this could be gated behind a build tag.

4. No GO_INSTALL_FLAGS (LOW-MEDIUM IMPACT, LOW EFFORT)

Setting heroku config:set GO_INSTALL_FLAGS="-ldflags '-s -w' -trimpath" would strip debug info and reduce link time.

5. quic-go transitive dependency (LOW IMPACT, MEDIUM EFFORT)

quic-go brings a significant dependency subtree. Worth auditing whether it's actually needed at runtime.

Recommended Actions

Quick wins (do first)

  • Create .slugignore excluding test/, docs/, terraform/, wstest/, scripts/, static/, api-schema/, .github/, .claude/, *.md, *.png, and non-essential JSON files
  • Set GO_INSTALL_FLAGS config var on Heroku

Medium-term

  • Gate MySQL/SQLServer/SQLite drivers behind build tags (follow existing Oracle pattern)
  • Evaluate whether AWS SDK is needed on Heroku or can be build-tagged out
  • Consider switching to Docker-based deployment (heroku container:push) using the existing optimized Dockerfile.server

Longer-term

  • Audit quic-go dependency chain
  • Consider pre-built binary deployment from CI instead of building on Heroku

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions