97
@flashcard_fen ·

Is it normal for a tiny Go HTTP service to build a 14MB binary Tooling

Four endpoints, one Postgres query, no fancy dependencies as far as I know. go build gives me 14MB, which surprised me because everyone talks about Go producing small self-contained binaries. Coming from Python where the file is 400 lines and that's the whole thing. Is this expected or did I import something enormous by accident?

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @easy_pace_ellis · 11mo ago · 3 replies

    Expected. You're shipping the whole runtime, the garbage collector, and everything statically linked, so a hello-world is already about 2MB before you write any code. 14MB for a real service with a database driver is normal.

    Easy trim: go build -ldflags="-s -w" drops the symbol table and DWARF info, usually 25-30% off. You lose readable stack traces in some tooling, which I'd think about before doing it in production.

    And the comparison that matters is not against a 400-line .py file, it's against the Python interpreter plus site-packages you have to install on the target box.

    212
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @committee_kim · 11mo ago

      Before you strip anything, run go tool nm -size -sort size yourbinary | head -40. It tells you what actually took the space, and about half the time it's one dependency you forgot you pulled in. go version -m yourbinary lists the module versions baked in too.

      52
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @flashcard_fen · 11mo ago

      Fair, when I put it that way my "small" Python service is a 900MB container image.

      68
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @secondshooter_v · 11mo ago · 2 replies

    Check your import graph before you optimise the linker flags. A single cloud SDK will add 8-10MB on its own, and people import the whole thing to make one signed URL. net/http/pprof in an init somewhere, a reflection-heavy ORM, or one of the big validation libraries will all show up.

    104
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @printbed_gremlin · 11mo ago

      Went from 31MB to 12MB by replacing one SDK import with a hand written request signer. Took an afternoon and I'd only do it if the size actually mattered to something.

      37
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @bruno_calder · 11mo ago

    UPX will squash it to around 4MB if you genuinely need it small for something like an embedded box or a CLI people download over a bad connection. Costs you a decompress on every start and antivirus products flag packed binaries constantly, so I would not do it for a server.

    31
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @barrier_first · 11mo ago

    In a container it matters even less than you'd think. Static binary on scratch or distroless gives you a ~15MB image total, and the layer barely changes between deploys if you cache dependencies properly. I've stopped caring below about 50MB.

    45
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @two_week_notice · 11mo ago · 2 replies

    Just use TinyGo, it produces binaries about a tenth the size.

    7
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @quiet_stacker · 11mo ago

      TinyGo doesn't support the full standard library, and net/http server support in particular is not something you'd want to bet a service on. It's for microcontrollers and wasm.

      5
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report