1 पॉइंट द्वारा GN⁺ 2025-06-09 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Railway ने user code से container image बनाने वाले builder को फिर से design किया है, और 1.4 करोड़ से ज़्यादा apps build करने के Nixpacks अनुभव को Railpack में लाया है
  • Nixpacks 80% users के लिए पर्याप्त था, लेकिन बाकी 2 लाख Railway users version management, image size और caching की सीमाओं से टकरा सकते थे
  • Railpack, Nix के commit-based version management की जगह major.minor.patch versions, dependency locking और Mise-based installation flow के जरिए build reproducibility बढ़ाता है
  • BuildKit LLB और Frontend सीधे generate करने से default Node image 38% और default Python image 77% छोटी हो गई, और environments के बीच share हो सकने वाला cache भी संभव हुआ
  • Railpack अभी Beta में है और service settings से enable किया जा सकता है; Railway व्यापक language support के बजाय पहले अक्सर इस्तेमाल होने वाली languages की maturity बढ़ा रहा है

Railway ने नया builder क्यों बनाया

  • Railway ने Railpack को Railway builder के अगले चरण के रूप में पेश किया
  • Railpack को Nixpacks से 1.4 करोड़ से ज़्यादा apps build करने के अनुभव के आधार पर शुरू से नया develop किया गया
  • Nixpacks लगभग 3 साल पहले जारी होने के बाद Railway में user code से images build करने का default तरीका बन गया
  • यह कुल users में से 80% के लिए अच्छा काम करता था, लेकिन बाकी 2 लाख Railway users को सीमाओं का सामना करना पड़ सकता था
  • Railway ने माना कि user base को 10 लाख से 10 करोड़ तक बढ़ाने के लिए builder को बड़े स्तर पर upgrade करना जरूरी है

Nixpacks को Nix में जिन सीमाओं का सामना करना पड़ा

  • सबसे बड़ी समस्या Nix का commit-based package version management था
    • हर package में केवल latest major version उपलब्ध होता है
    • version nixpkgs repo के किसी specific commit से बंधा होता है
  • सभी patch versions को support करने की कोशिश version string और commit SHA को सीधे map करने वाली structure बन गई, जो Nix version management से परिचित न होने वाले contributors के लिए स्पष्ट या maintain करना आसान नहीं था
  • Node और Python जैसी languages में अंततः केवल latest major version ही support हो पाया
  • latest package versions support करने के लिए commit SHA update करने पर दूसरे package versions भी साथ में बदल सकते थे
    • default version बदलने पर पहले काम कर रहे user builds के अचानक error से fail होने की संभावना बढ़ जाती थी
    • Railway के लिए users का latest packages तक access न होना उतना बुरा नहीं था, जितना सफल build का अचानक टूट जाना

Image size और caching की समस्याएं

  • Nixpacks जिस तरह Nix से dependencies लाता था, वह अक्सर बड़ी image size बनाता था
  • build और runtime के लिए जरूरी Nix और संबंधित packages/libraries एक ही /nix/store layer में चले जाते थे
  • Nix dependencies को अलग layers में बांटने का तरीका न होने से final image size घटाने की सीमा थी
    • Railway इसे Nix की अपनी समस्या नहीं, बल्कि Nixpacks में Nix इस्तेमाल करने के तरीके की समस्या मानता है
  • caching में भी यह control करना मुश्किल था कि layer cache कब invalidate होगा
  • Railway हर build में deployment ID environment variable inject करता है
    • Dockerfile में यह variable जुड़ने के बाद चलने वाली layers हमेशा invalidate हो जाती थीं और cache नहीं हो सकती थीं
  • Nix के core elements को users से छिपाने वाला approach भी ठीक नहीं बैठा
    • वे चाहते थे कि users को यह समझने की जरूरत न पड़े कि derivation क्या है, या Node 22.14.0 unstable channel के किसी specific archive version में क्यों है

Railpack के structural बदलाव

  • Railway ने Nixpacks में आई समस्याओं को हल करने के लिए Railpack बनाया
  • Nix से हटते हुए नाम भी Nixpacks से Railpack हो गया
  • BuildKit libraries के कारण codebase Rust से Go में बदला गया
  • Railpack final image generation को ज्यादा directly control करता है
    • BuildKit LLB और Frontend सीधे generate करता है
    • Nixpacks की तुलना में default Node image 38% और default Python image 77% छोटी हो गई
    • version resolution और अधिकांश package installation के लिए Mise का इस्तेमाल करता है
    • भविष्य में दूसरे executable sources support करने की गुंजाइश भी छोड़ता है
  • सफल build में इस्तेमाल की गई dependencies को lock किया जा सकता है
    • default Node version 22 से 24 हो जाने पर भी build टूटने से बचाया जा सकता है
  • BuildKit secrets का इस्तेमाल करके secret environment variables को build logs या final image में दिखने से रोकता है

Railpack build कैसे काम करता है

  • Railpack process तीन चरणों में बंटा है
    • Analyze: code देखकर install किए जाने वाले packages, चलाए जाने वाले commands और start command तय करता है
    • Plan: कई stages से बना JSON-serializable build plan बनाता है, जहां हर stage दूसरे stages या पूरी image से input लेता है
    • Generate: plan के inputs और outputs के अनुसार BuildKit build graph बनाता है
  • Dockerfile linear होता है, लेकिन BuildKit graph कहीं ज्यादा parallel ढंग से बना होता है
  • हर command multi-stage build के अपने stage में चलता है, जिससे input layers और final file system assemble करने के तरीके पर बारीक control मिलता है
  • Railpack सभी जरूरी build steps वाला build plan generate करता है
    • हर stage जरूरी previous stages या images को खास तौर पर define करता है
    • यह format Nixpacks में इस्तेमाल हुए तरीके से ज्यादा low-level है
    • plan को LLB format graph में बदलकर interpret किया जाता है
  • BuildKit अंत से शुरू कर पीछे की ओर काम करता है, संभव होने पर cache से लेता है, और जरूरत पड़ने पर ही commands चलाकर requested layer resolve करता है
  • किसी specific environment variable के बदलने पर layer invalidate करने के लिए Railpack इस्तेमाल किए गए variable values को hash करता है, और उस hash वाली file को input file system में mount करता है
    • अगर code और इस्तेमाल किए गए variables नहीं बदलते, तो layer cache hit होता है
  • Railpack image बनने के तरीके को पूरी तरह define कर सकता है

Railpack से संभव हुए काम

  • Vite, Astro, CRA, Angular static sites को zero-config में build और deploy किया जा सकता है
  • build और Railway UI के बीच integration ज्यादा tight हो गया है
  • Railpack release के बिना भी language के latest versions support किए जा सकते हैं
  • project के कई environments में optimized layer caching इस्तेमाल की जा सकती है

अभी इस्तेमाल करने का तरीका और support scope

  • Railpack अभी Beta में उपलब्ध है और service settings से activate किया जा सकता है
  • इसे पहले से railway.com और central station builds में इस्तेमाल किया जा रहा है
  • फिलहाल support में ये शामिल हैं
    • Node
    • Python
    • Go
    • PHP
    • Static HTML deployment
    • Vite, Astro, CRA, Angular static sites का basic support
  • Railway का लक्ष्य ऐसा environment बनाना है जहां frontend और backend दोनों आसानी से deploy किए जा सकें
  • framework और language support लगातार जोड़ा जा रहा है
    • requests Help Station पर ली जा सकती हैं
    • core API और abstractions तय होने तक, व्यापक support के बजाय ज्यादा इस्तेमाल होने वाली languages में depth को प्राथमिकता दी जा रही है
  • Railpack open source है और documentation railpack.com पर उपलब्ध है

1 टिप्पणियां

 
GN⁺ 2025-06-09
Hacker News की राय
  • मैं Nix का प्रशंसक हूं, लेकिन Railway के Nix से दूर जाने की आलोचना नहीं करना चाहता। बस कुछ शिकायतों को और स्पष्टीकरण की जरूरत लगती है
    Nixpkgs शानदार है, लेकिन यह Nix के समान नहीं है, और अगर आप toolchain का कोई मनचाहा version लाना चाहते हैं तो Nixpkgs आदर्श नहीं है। Rust का मनचाहा version लाने वाले Nix tools पहले से ही बहुत अच्छे हैं, और दूसरे Nix-आधारित development tools ने भी दिखाया है कि इसे अच्छी तरह कैसे संभाला जा सकता है
    “Nix dependencies को अलग layer में बांटने का कोई तरीका नहीं है” यह बात भी समझ नहीं आती। आप जैसे चाहें वैसे बांट सकते हैं, और Nixpkgs के built-in Docker tools में भी इसका कुछ support है
    Rust से Go पर जाना सीधे Nix से जुड़ा नहीं है, लेकिन दिलचस्प है, और ऐसा भी लगता है जैसे Railpacks और Nixpacks अलग-अलग लोगों ने बनाए हों। मैंने देखा है कि जब Nix से परिचित न होने वाले लोग संगठन के अंदर किसी अधूरे Nix solution को संभाल लेते हैं तो काफी खराब स्थिति बनती है, इसलिए workplace में आमतौर पर ऐसी स्थिति बनने के डर से Nix इस्तेमाल नहीं करता

    • मैं Nix इस्तेमाल नहीं करता, लेकिन “Nixpkgs, Nix नहीं है” वाली प्रतिक्रिया थोड़ी dismissive लगती है। Nixpkgs default है और अगर alternatives के लिए अतिरिक्त research और मेहनत चाहिए, तो ज्यादातर users के लिए व्यवहार में वही Nix है
      “जैसे चाहें वैसे layers बांट लें” में भी अहम बात यह है कि क्या वह स्पष्ट, सरल और default behavior है
    • Nix में basic usability की समस्या आने पर हर बार “workaround है” वाला जवाब दोहराया जाना थका देता है। उस workaround के लिए परंपरागत/मुंहजबानी ज्ञान चाहिए, मुख्यधारा की languages से बिल्कुल अलग चलने वाली language में दर्जनों से सैकड़ों lines लिखनी पड़ती हैं, और error messages व standard library documentation भी अच्छे नहीं हैं
      लोग Nix से इसलिए नाराज नहीं हैं कि यह Turing-complete नहीं है, बल्कि इसलिए कि यह उस ecosystem के idiomatic projects के साथ सीधे फिट होने वाली सरल first-class API नहीं देता, जिससे यह जितनी समस्याएं हल करता है उससे ज्यादा समस्याएं पैदा कर देता है
      अगर Nix इस्तेमाल करने वाले हर project का अंत Nix की समस्याएं ठीक करने के लिए खुद modules लिखने में होता है, तो अच्छी documentation वाले mainstream tools के बजाय Nix इस्तेमाल करने की वजह कमजोर है। इस मामले में भी ठीक वही दिख रहा है, और ज्यादातर लोग शायद बस Docker चुनेंगे
      developers के लिए बने product का व्यावहारिक developer experience समस्याओं को geologic time scale के बजाय तेज गति से हल करने की जगह वैचारिक रूप से शुद्ध flakes से चिपके रहना निराशाजनक है। मुझे पता है कि यह voluntary contribution है, लेकिन खराब user experience के कारण practically इस्तेमाल कठिन हो जाने वाली चीजों में इतनी ज्यादा technical मेहनत लगना बहुत अफसोसजनक है
    • जिस बात को नजरअंदाज करना आसान है, वह यह है कि Railway के users वे developers हैं जो arbitrary packages के लिए अपनी dependencies और versions specify करना चाहते हैं
      Nix जिस तरह Nixpkgs structure के साथ काम करता है, उसमें किसी package version को pin करने का मतलब पूरे nixpkgs tree के commit को pin करना होता है। node/python/ruby package builds, package directory के बाहर tree की state पर भी निर्भर करते हैं, इसलिए version और commit के बीच mapping की जरूरत पड़ती है
      यह abstraction leak करती है, इसलिए Railway को इसे users के सामने लाना पड़ता है, और user तो बस yarn add new-fancy-nodejs-package-with-linked–native-deps करना चाहता था, लेकिन उसे nixpkgs repository की कई states को मिलाने की स्थिति से जूझना पड़ सकता है
      सीमित scope वाले use case में Nix को Nixpkgs के बिना इस्तेमाल करना ठीक हो सकता है, लेकिन Railway जैसे platform पर इसे justify करना मुश्किल दिखता है
    • “Nix != Nixpkgs” जैसी बात मैंने FreeBSD ports के संदर्भ में FreeBSD आजमाते समय भी सुनी थी। pkg आमतौर पर ठीक काम करता था, लेकिन एक दिन ports से vim को custom USE flags के साथ compile करने की कोशिश की, तो 20 से ज्यादा dependencies आ गईं और हर make menuconfig पर options पूछे गए, फिर 23 में से 16वां package “इसके लिए वह चाहिए, और उसके लिए Fubar3.32.1 चाहिए, लेकिन Fubar3 तो Fubar4 से deprecated हो चुका है” जैसी बात कहकर fail हो गया, तो मैंने हार मान ली
      समझता हूं कि Core OS developers 10,000 से ज्यादा packages को सब support नहीं कर सकते, लेकिन यह भी साफ करना चाहिए कि अगर असल में custom features enable करके इस्तेमाल करने की कोशिश करें तो failure की संभावना ज्यादा है। या फिर ports में आने से पहले स्वतंत्र रूप से बनाए गए standard build का सफल होना criterion होना चाहिए, और जो compile नहीं होते उन्हें ports list से हटा देना बेहतर है
    • मुझे यह अच्छी तरह कही गई बात लगती है। साथ में कहूं तो nixpkgs, Nix खुद नहीं है, लेकिन nixpkgs ही अच्छी चीजों में से एक भी है। NixOS इस्तेमाल करते हुए पहली बार मैं Linux kernel का latest version release वाले दिन ही इस्तेमाल कर रहा हूं, और यह काफी शानदार है। उम्र बढ़ने के साथ मैंने Debian Stable को भी स्वीकार करना सीख लिया है, लेकिन हमेशा कुछ साल पीछे लौटने जैसा महसूस होता है
      Nix language की घंटों आलोचना की जा सकती है, लेकिन यह पुरानी है, उस समय अपनी तरफ से best effort थी, और अब शायद इसे बदलने का value बहुत बड़ा नहीं है। Nix build system काफी primitive लगता है, और अक्सर वे चीजें भी फिर से build करता है जिन्हें फिर से build करने की जरूरत नहीं लगती। उदाहरण के लिए NixOS install ISO के build का बड़ा हिस्सा kernel को दी जाने वाली command line console=ttyS2,1500000n8 पर depend करता है, इसलिए सिर्फ serial port speed बदलने पर भी करीब 3 मिनट का build चाहिए। यह हास्यास्पद है, लेकिन इसकी वजह से मैं Nix छोड़ूंगा नहीं; बस अपनी builds में ऐसा allow नहीं करूंगा
      Docker images के लिए Nix, मेरी नजर में वह क्षेत्र है जहां Nix सबसे कमजोर है। बहुत पहले Go software बनाते समय container image में Postgres का pg_dump binary जोड़ना पड़ा था। infrastructure team के सुझाव पर Nix इस्तेमाल किया तो compressed Go binary वाली 50MB image किसी अज्ञात वजह से 1.5GB हो गई। pg_dump 464KB है। आखिर में Bazel और rules_debian से apt package install किया, और distroless पर image कहीं ज्यादा साफ और छोटी हो गई। वास्तविक Nix experience के आधार पर लगता है कि Nix system हमेशा 1.4GB का बन जाता है। install ISO भी 1.4GB, नई install की गई machine भी 1.4GB
      बड़े C++ project को build करना चाहने की स्थिति पहले से ही अच्छी तरह paved path है, और C++ को Rust से बदल देने पर मूल बात नहीं बदलती। ऐसे build systems हैं जो library situation को कम दर्दनाक बनाते हैं, और वे भी Nix जितने complex हैं, लेकिन इस use case के लिए कुछ ज्यादा fit भी हैं। Nix दूसरे लोगों के software और nixpkgs को build करने वाला build system बनने की कोशिश करता है, इसलिए यह बहुत general जगह पर बैठता है। अपने software को build करने के लिए design किए गए build systems आमतौर पर उस काम को बेहतर करते हैं। व्यक्तिगत तौर पर मैं Bazel से संतुष्ट हूं और Go-only projects के go build के अलावा शायद ही कुछ और इस्तेमाल करूं, लेकिन options बहुत हैं। 99% मामलों में Nix की जगह उन्हीं का इस्तेमाल करें, और ताकि लोग home-manager से latest version install कर सकें, एक flake लिख दें
  • version चुनने वाला हिस्सा अजीब लगता है। nixpkgs का version किसी system को चलाते या build करते समय तो समझ आता है, लेकिन अगर आप platform के रूप में runtime या compiler दे रहे हैं, तो devenv की तरह version सीधे उपलब्ध कराने का तरीका चाहिए
    पुराने nodejs देने के लिए अगर पुराना system build करना पड़े, तो dependencies के security patches छूट जाते हैं। Devenv इसे, उदाहरण के लिए, https://github.com/cachix/nixpkgs-python से “सभी Python versions को Nix में हर घंटे up-to-date रखना” जैसे तरीके से संभालता है
    Railway का हर build में deployment ID environment variable inject करना installation के अगले layer में भी किया जा सकता था। packages को कई layers में बांटा भी जा सकता है, और layers की संख्या घटाने के लिए bundle-level automation भी है

  • “Nix में खुद समस्या नहीं है, समस्या हमारे इस्तेमाल करने के तरीके में थी” सही tool को सही काम में इस्तेमाल करें का अच्छा उदाहरण है। Nix कुछ use cases के लिए शानदार है और कुछ के लिए बेहद खराब
    समस्या यह है कि Nix की learning curve इतनी ज्यादा है कि जब तक आप इतना समझते हैं कि फैसला कर सकें, तब तक आप इतना समय लगा चुके होते हैं कि वापस लौटना अफसोसजनक लगता है, और अपनी मूल जरूरत हल करने के लिए उसे जबरन fit करने लगते हैं

    • मुझे भी कुछ ऐसा ही लगता है, लेकिन कुछ मायनों में Nix दूसरे operating systems की तुलना में ज्यादा सामान्य programming paradigm के करीब है। हम बस operating system को उस तरह से सोचने के आदी नहीं हैं। Nix expressions में inputs होते हैं, package repositories और कई key-value pairs जाते हैं, और output के रूप में Linux system निकलता है। कुछ साल बाद यह शायद काफी ज्यादा सामान्य लगे
      इसी paradigm की वजह से AI के लिए specification के मुताबिक shell.nix या configuration.nix बनाना बहुत आसान है। जैसे इसमें Python packages, Linux packages, environment variables, path items वगैरह हो सकते हैं
      repository में उस package को पूरी तरह support करने वाला environment शामिल करने के लिए मैं ऐसी चीजें अक्सर इस्तेमाल करता हूं। flakes इस्तेमाल करने से यह ज्यादा reproducible होगा, लेकिन मेरी समझ में flake.nix, version pinning वाले shell.nix जैसा है और मैं अभी भी सीख रहा हूं
  • ऐसा लगता है जैसे जहां version नहीं है, वहां जबरन version ठूंसने की कोशिश की जा रही है। यह square cube को round hole में डालने जैसा है
    “default version” उस पर depend करने वाली चीजों को तोड़ देता है—इसका मतलब क्या है, समझ नहीं आता। यह Docker का :latest tag इस्तेमाल करने जैसा है, और फिर हर बार नया server शुरू होने पर उसके पिछले “default” image से अलग version होने की वजह से टूटने पर हैरान होना
    इस blog post की व्याख्या मुझे बिल्कुल समझ नहीं आती। ऐसा लगता है जैसे इन्हें software का “version” क्या होता है, यह बिल्कुल नहीं पता
    “Nix dependencies को अलग layers में बांटने का कोई तरीका नहीं है” भी क्यों, यह समझ नहीं आता। जाहिर है /nix/store को जितनी जरूरत हो उतनी layers में बांटा जा सकता है। शक होता है कि इन्हें containers और Nix का इस्तेमाल शुरू से करना भी आता है या नहीं
    ऐसी साफ अपरिपक्वता देखकर यह हैरानी की बात नहीं कि उनके सुझाए solution से भी सड़ी मछली जैसी बू आती है। यह typical NIH syndrome है, और बहुत संभव है कि जिन समस्याओं को वे Nix से हल नहीं कर पाए, वही नई “solution” में भी फैल जाएं

    • Nix न इस्तेमाल करने से मुझे कोई खास आपत्ति नहीं, खासकर जहां उसका मतलब ही न बनता हो। लेकिन कुछ घंटे लगाकर देखा जा सकता है कि लोग उन problems को पहले से कैसे solve करते हैं; जो वजहें असल में problem नहीं हैं उनके आधार पर working system को scratch से फिर बनाना मूल रूप से अजीब लगता है
      जैसा दूसरे लोगों ने कहा, nix2container और flakes शायद उनकी सारी समस्याएं हल कर देंगे
      version management की बात करें तो 3 साल पहले लिखे गए flakes आज भी बिल्कुल उन्हीं versions और उसी output के साथ build होते हैं, जैसे पहली बार लिखते समय होते थे
      हालांकि सुनने में ऐसा लगता है जैसे platform के रूप में market में जाकर funding raise करनी है
      edit: अभी nixpacks का GitHub देखा, और तुरंत दिखा कि वे oxalica का rust-overlay[0] नहीं, बल्कि nixpkgs का rustPlatform इस्तेमाल कर रहे हैं, जबकि Rust problem को बस हल्का-सा search करने पर भी वह मिल जाता। rust-overlay मेरे इस्तेमाल किए overlays में सबसे उपयोगी और powerful overlays में से एक है
      [0] https://github.com/oxalica/rust-overlay
    • अगर लक्ष्य VC funding पाना है, तो Nix wrapper की तुलना में deployment platform ज्यादा बिकेगा
  • nix2container[1] सच में dependencies को अलग layers में बांट सकता है। image के लिए जरूरी dependencies में से सिर्फ कुछ को रखने वाला layer explicit रूप से बनाया जा सकता है, और example भी इस section में है: https://github.com/nlewo/nix2container?tab=readme-ov-file#is...
    उदाहरण के लिए अगर images bash इस्तेमाल करती हैं, तो bash closure वाला layer explicit रूप से बनाया जा सकता है। यह layer सभी images में reuse होगा, और सिर्फ तब rebuild और repush होगा जब वह bash closure बदलेगा
    single /nix/store layer की वजह से image बड़ी हो जाती है—यह default nixpkgs.dockerTools.buildImage function पर लागू होता है, लेकिन nix2container या nixpkgs.dockerTools.streamLayeredImage पर सही नहीं है। ये tools layers को Nix store में लिखने के बजाय existing store paths का इस्तेमाल करके image को सच में push करने वाली script बनाते हैं। nix2container implementation सभी layers के Nix store paths बताने वाली JSON file बनाता है, और Skopeo इस JSON को consume करके image को Docker daemon, registry, podman वगैरह में push करता है
    संदर्भ के लिए, मैं nix2container का author हूं
    [1] https://github.com/nlewo/nix2container

    • nix2container की वजह से मैं इसे AWS ECR deployment में इस्तेमाल कर रहा हूं, और builds के बीच iteration time घटकर single-digit seconds हो गया है
    • Docker image size की समस्या थी, इसलिए nix2container को experiment करने के लिए समय निकाल रहा था। काम के लिए धन्यवाद
  • यहां core problem language package managers द्वारा बढ़ावा दिए जाने वाले custom version soup वाले रवैये से चिपके रहना है। यह तरीका पूरी तरह unsustainable है
    विकल्प Mise में packages के बीच version constraints समझने की क्षमता नहीं दिखती, और ऐसा भी नहीं लगता कि installed हर package आसपास के versions के साथ ठीक चलता है या नहीं, इसके लिए tests चलाता हो। तो आपको वही चीज बिल्कुल नहीं मिलती

  • कस्टम version soup टिकाऊ नहीं है, लेकिन लोग इसे इसलिए इस्तेमाल करते रहते हैं क्योंकि आम तौर पर यह ठीक काम करता है। इसके ठीक काम करने की एक वजह यह है कि operating system level libraries एक बहुत ज़्यादा conservative अलग दुनिया से आती हैं, और backward compatibility तोड़ने से जितना हो सके बचती हैं
    इसलिए आप किसी stable और अच्छी तरह maintained operating system को आधार बना सकते हैं, उसके ऊपर mise या asdf जैसे tools से tools और language runtimes का कस्टम version soup रख सकते हैं, और फिर app चला सकते हैं। यह शायद ही कभी टूटता है। जब टूटता है, तो versions और छोटी-मोटी fixes से छेड़छाड़ करके उसे फिर चला लेते हैं और आगे बढ़ जाते हैं। इसके टूटने की बात annoying है, लेकिन अहम नहीं। friction बढ़ाना, learning मांगना, या ज़्यादा काम मांगना समय की बर्बादी है
    इसके उलट कुछ लोग ऐसा समाधान ढूंढते हैं जिससे यह फिर कभी न टूटे। उनके लिए समस्या अहम है, इसलिए अगर समाधान friction, learning और extra work मांगे तो भी ठीक है। ऐसे लोग Nix चाहते हैं
    ज़्यादातर लोग पहले group में आते हैं, इसलिए Railway जैसी grow करना चाहने वाली company आखिरकार उसी group के लिए सही solution चुनती है

    • “कस्टम version soup” वाला attitude असल में क्या मतलब रखता है, और alternative क्या है, थोड़ा और समझा सकते हैं?
    • सही तरह से किया जाए तो दोनों मिल सकते हैं। उदाहरण के लिए Cargo.lock file से Nix में Rust package build करना मामूली बात है। nixpkgs कस्टम version soup की उलटी दिशा में है, लेकिन Nix खुद उस तरीके को भी ठीक-ठाक handle कर सकता है
  • DevOps/SRE के तौर पर काम करने के अनुभव से, जब कोई dependencies वगैरह manage करने वाला system बनाने की कोशिश करता है, तो आम तौर पर दो रास्तों में से एक पर जाता है। Python को उदाहरण के तौर पर ले सकते हैं
    विकल्प 1: “एक बड़ा shared monorepo इस्तेमाल करें।” फायदा यह है कि सब कुछ एक जगह होता है, जो चाहिए वह included होता है, और सब एक ही चीज़ इस्तेमाल करते हैं इसलिए vulnerabilities जैसी समस्याएं fix करना आसान होता है। नुकसान यह है कि कोई न कोई हमेशा कोई special version चाहता है, gradual rollout मुश्किल होता है इसलिए changes अक्सर big bang बन जाते हैं, और “छोटा Docker version कैसे बनाएं?” वाला सवाल आता है
    विकल्प 2: “हर किसी का अपना conda/venv हो।” फायदा यह है कि हर किसी को ठीक वही मिलता है जो वह चाहता है, अनावश्यक packages नहीं इस्तेमाल होते, और staged upgrades आसान होते हैं। नुकसान यह है कि “आखिर conda environments कितने हैं?” वाली स्थिति बन जाती है, अलग-अलग groups की libraries शायद उसी Python library combination के साथ test न हुई हों, और अलग-अलग conda environments कहां हैं यह भी पता न होने से vulnerability management nightmare बन जाता है
    इसलिए “यह नया तरीका सब कुछ solve कर देगा” जैसी बातों पर मैं हमेशा skeptical रहता हूं। career जितना लंबा होता जाता है, “solutions नहीं होते, सिर्फ trade-offs होते हैं” वाली बात उतनी ही सच लगने लगती है

  • Nix का थोड़ा ही experience होने के बावजूद, यहां के points ज़्यादा सही नहीं लगते
    कहा गया है कि “Nix के version management से परिचित न होने वाले contributors के लिए यह clear या maintainable नहीं है”, “Node और Python में सिर्फ latest major versions support होने लगे”, लेकिन मुझे नहीं समझ आता कि यह unmaintainable क्यों है। अगर वजह यह है कि available versions की list बनानी पड़ती है, तो सवाल है कि क्या इसे automate नहीं किया जा सकता
    उससे भी आगे, समझ नहीं आता कि Railway user के Nix इस्तेमाल करने के तरीके को define क्यों कर रहा है। Nix की core बातों में से एक यह नहीं है कि आप खाली machine को मनचाहे packages के exact versions से configure कर सकते हैं? Railway user और उस version के बीच में आकर restriction क्यों लगाए, यह समझ नहीं आता
    अगर structure ऐसा है कि user सीधे Nix को देख ही नहीं पाता, तब भी असली सवाल बचता है। क्या package versions की list automate नहीं की जा सकती?

    • version restriction इस fact से आता है कि Nix cache पुराने versions को रखकर नहीं चलता। इसलिए पुराने version इस्तेमाल करें तो source से compile करना पड़ता है। सुनने में ऐसा लगता है कि वे पुराने versions के लिए खुद cache provide नहीं करना चाहते थे, लेकिन इसमें इतना बड़ा effort लगेगा ऐसा नहीं लगता
      सच कहूं तो दिए गए reasons बहुत मजबूत नहीं लगते। शायद जिसने Nix introduce किया था वह चला गया, और बचे हुए लोगों को यह खास पसंद नहीं था। language खुद भी बहुत अच्छी नहीं है, और पुराना documentation भी शानदार नहीं था
      फिर भी, उन्होंने जो stack चुना है उसे मैं पर्याप्त नहीं जानता, लेकिन curiosity है कि क्या वह Nix के करीब की determinism देता है। अगर नहीं, तो आगे चलकर यह परेशानी खड़ी कर सकता है या operations को और मुश्किल बना सकता है
    • लेख में कहा गया है कि “Nixpacks जिस तरीके से dependencies खींचता है, वह एक single /nix/store layer वाली huge image तक ले जाता है, जिसमें build और runtime के लिए जरूरी सभी Nix-related packages और libraries होती हैं”
      यह कहना कुछ ऐसा है जैसे “car को आगे नहीं चला पाए, इसलिए car छोड़ रहे हैं।” यह उन चीज़ों में से एक है जो Nix सबसे reliably कर सकता है। result binaries में सच में referenced runtime dependencies को /nix/store hash string matching से automatically detect करता है
      अगर वे यह नहीं कर पाए, तो वे इसे काफी अजीब तरीके से इस्तेमाल कर रहे थे या कुछ गंभीर रूप से गलत किया था। पहले तो यह सोचना ही मुश्किल है कि Nix को इसे automatically solve करने से रोकने का तरीका क्या होगा
      इसलिए मैं उनके Nix experience को बहुत deeply नहीं लूंगा। version management वाली बातें ऐसी बेहद common problems हैं जिनसे सब जूझते हैं, इसलिए अगर उन्होंने solution की कोशिश की होती तो वह ज़्यादा interesting होता
    • user को सीधे Nix न दिखाने वाला structure है — मेरी समझ कम से कम यही है
    • project में Dockerfile बिल्कुल न हो तब भी code Railway पर push करें तो Nixpacks से image build कर देता है। build logs में Nix-related content दिखेगा, लेकिन ज़्यादातर चीज़ें पीछे चलती हैं
  • Nix arbitrary version guarantee नहीं, बल्कि commit guarantee देता है। edge cases आएंगे तो glibc changes या conflicting shared libraries की वजह से आपको परेशानी होगी
    शायद थोड़ा देर हो गई है, लेकिन Nix-idiomatic तरीके से काम करवाने के लिए consulting देने में खुशी होगी। product अच्छा दिखता है

    • Nix shared library incompatibility problems को बेहद conservative तरीके से solve करता है। कुछ भी बदले — meaningful change हो या नहीं, सिर्फ comment fix, documentation change, या test case add करने पर भी — सभी dependencies फिर से build करता है
      इतना ही नहीं, dependencies की dependencies, फिर उनकी dependencies, और यह सिलसिला चलता रहता है, इसलिए बड़े rebuilds अक्सर होते हैं
      shared library conflicts तो बचेंगे, लेकिन यह solution बेहद wasteful है और development को भी painful बना सकता है। nixpkgs का staging process देखें तो पता चलेगा
    • Nix की value proposition पूरी तरह समझता हूं। लेकिन “परेशानी होगी” वाला phrase थोड़ा exaggeration लगता है। ज्यादा से ज्यादा कहें तो “Nix के मुकाबले काफी अहम guarantees खो देंगे” इतना ही है
      फिर भी, लगता है कि यह दुनिया के 95% software से ज़्यादा “ठीक से काम करने की संभावना के साथ packaged” होगा
  • समझ नहीं आता कि nixpkgs hash पर depend करने के बजाय अपना derivation क्यों नहीं बना सके