[{"data":1,"prerenderedAt":435},["ShallowReactive",2],{"project-44323253":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":28,"sentiment":29,"stance_mix":30,"scored_comments":35,"aspects":36,"strip":43,"post_text":46,"what":47,"said":87,"maker_in_thread":188,"shape":198,"grid":202,"attempts":398,"same_week":399,"maker_shows":38,"maker_hidden":428,"reader_version":429,"card":430},"44323253","ExTracker","A new BitTorrent tracker in Elixir","title","Show HN: I wrote a new BitTorrent tracker in Elixir","https:\u002F\u002Fgithub.com\u002FDahrkael\u002FExTracker","github.com","dahrkael",1750373389,2025,394,72,120,3837,4,"legend","infrastructure","bittorrent tracker","other",[21,24,25,26,27],"elixir","ets","udp tracker","opentracker","debated",0.11,{"positive":31,"neutral":32,"mixed":33,"critical":34},7,10,0,6,23,{"design":37,"execution":39,"performance":40,"docs":41,"idea":42},{"positive":38,"critical":38},1,{"positive":38,"critical":38},{"positive":33,"critical":33},{"positive":33,"critical":33},{"positive":38,"critical":18},[38,33,33,44,45,45,33,33,45,33,33,45,45,33,33,33,33,33,33,33,45,33,45,33,33,33,38,45,44,45,33,44,44,33,33,33,33,38,38,38],5,3,"Hello everyone!\n\nI'm currently in a journey to learn and improve my Elixir and Go skills (my daily job uses C++) and looking through my backlog for projects to take on I decided Elixir is the perfect language to write a highly-parallel BitTorrent tracker. So I have spent my free time these last 3 months writing one! Now I think it has enough features to present it to the world (and a docker image to give it a quick try).\n\nI know some people see trackers as relics of the past now that DHT and PEX are common but I think they still serve a purpose in today's Internet (purely talking about public ",{"problem":48,"audience":54,"pricing":54,"motivation":55,"time_to_build":62,"stack":66,"openness":84,"stage":85,"team_size":86},{"value":49,"source":50,"evidence":51},"Public BitTorrent trackers with few new developments; wants a fast, crash-resistant tracker","maker",[52],{"id":53},"post",null,{"value":56,"source":50,"evidence":57},"Learning Elixir and Go; the tracker became more fun than the project it was needed for",[58,59],{"id":53},{"id":60,"by":11,"text":61},"44325860","I started because I needed a tracker for another project but the tracker turned to be more fun to make. I did glance over other trackers code but their code tends to be either…",{"value":63,"source":50,"evidence":64},"About 3 months of free time",[65],{"id":53},[67,71,80],{"value":68,"source":50,"evidence":69},"Elixir",[70],{"id":53},{"value":72,"source":50,"evidence":73},"ETS",[74,77],{"id":75,"by":11,"text":76},"44325659","in my case using the in-memory ETS has been the best decision, it lets me read&write the peer's data concurrently each on its own process so contention and latency are minimal.…",{"id":78,"by":11,"text":79},"44325777","I feel like ETS has been the real killer feature to pull this, being able to concurrently read and write from protected tables makes the whole thing incredibly parallel",{"value":81,"source":50,"evidence":82},"Docker",[83],{"id":53},"open_source","beta","solo",{"praise":88,"objections":108,"requests":134,"questions":160,"alternatives":175},[89,97,101],{"value":90,"source":91,"evidence":92},"Impressive, well-written Elixir code","commenter",[93],{"id":94,"by":95,"text":96},"44334153","andyleclair","This is really good, my dude. I took a peruse through the code and I'm definitely impressed, this is like, code I would expect my senior engineers with elixir experience to turn…",{"value":98,"source":50,"evidence":99},"ETS makes it highly parallel",[100],{"id":78,"by":11,"text":79},{"value":102,"source":91,"evidence":103},"Elixir suits protocol parsing and concurrency",[104],{"id":105,"by":106,"text":107},"44325213","uncircle","Not sure about C++ devs, but Erlang\u002FElixir are great to handle parsing of protocols, with its implementation of pattern matching. Also, makes the code much cleaner because…",[109,116,126],{"value":110,"source":91,"evidence":111},"Design is procedural rather than OTP-first",[112],{"id":113,"by":114,"text":115},"44326028","nesarkvechnep","I really wished to see an OTP-first design. Unfortunately for me, the code is almost procedural as it's touching ETS or Application, which is built on ETS, in nearly every…",{"value":117,"source":91,"evidence":118},"HTTPS does not work out of the box",[119,123],{"id":120,"by":121,"text":122},"44324803","KomoD","I tried it, couldn't get HTTPS to work. Also my console gets spammed with: 04:43:20.160 [warning] invalid 'event' parameter: size: 6 value: \"paused\" but it seems to work. I…",{"id":124,"by":11,"text":125},"44325803","Telemetry for the HTTP side is in my ToDo list yes, since I'm using a 3rd party library for the webserver I still need to figure out how to do it right. For HTTPS to work you…",{"value":127,"source":91,"evidence":128},"Console spam from BEP 21 paused event",[129,130],{"id":120,"by":121,"text":122},{"id":131,"by":132,"text":133},"44325719","bill876","The \"paused\" event is part of BEP 21. Clients send it to the tracker to let it know that the client is still incomplete, but won't download anymore. For example, because a user…",[135,146,153],{"value":136,"source":91,"evidence":137},"Add OpenTelemetry or Logger instead of IO.puts",[138,142],{"id":139,"by":140,"text":141},"44324351","voicedYoda","Well done. Couple quick notes, move to a logger instead of using IO.puts. Also consider adding OTel.",{"id":143,"by":144,"text":145},"44324623","solid_fuel","I'll second this, just using the built in Logger [0] and Telemetry [1] applications would be fine, opentelemetry or anything else can be added to the telemetry hooks easily to…",{"value":147,"source":91,"evidence":148},"Support private tracker use",[149],{"id":150,"by":151,"text":152},"44324013","bavell","Very cool! Is this suitable for using as a private tracker?",{"value":154,"source":91,"evidence":155},"Benchmarks against opentracker",[156],{"id":157,"by":158,"text":159},"44323981","abrookewood","Hey congrats on the launch! Can you provide any details on how it runs compared to opentracker? I'm really interested in the performance etc.",[161,168],{"value":162,"source":91,"evidence":163},"How does performance compare to opentracker?",[164,165],{"id":157,"by":158,"text":159},{"id":166,"by":11,"text":167},"44325738","For small trackers opentracker is probably faster and use a bit less memory. Where extracker is gonna shine compared to it is when core count starts having 2 digits. I still have…",{"value":169,"source":91,"evidence":170},"Is it suitable as a private tracker?",[171,172],{"id":150,"by":151,"text":152},{"id":173,"by":11,"text":174},"44325770","not out of the box but it can be done. All the required moving parts are there (hash whitelist support, udp path parsing, peer rejection, etc).",[176,180,184],{"value":27,"source":50,"evidence":177},[178,179],{"id":53},{"id":166,"by":11,"text":167},{"value":181,"source":50,"evidence":182},"aquatic",[183],{"id":53},{"value":185,"source":50,"evidence":186},"torrust",[187],{"id":53},{"comments":189,"answered":34,"key":190},11,[191,194,197],{"id":192,"text":193},"44326242","On my first try I did write it in a more OTP-y style but the scaling potential for this very specific flow is just not the same. In the end a torrent tracker is just a…",{"id":195,"text":196},"44325746","I use Logger through all the project except for the table pretty print. Telemetry is optionally available in prometheus and html formats:…",{"id":166,"text":167},{"commenters":199,"max_depth":32,"maker_replies":189,"first_comment_mins":200,"lifespan_hours":201},45,81,233,[203,205,207,211,215,218,221,224,226,230,231,233,237,240,243,245,247,249,252,255,259,260,263,266,269,272,275,278,281,283,285,288,290,292,294,296,298,301,303,306,311,314,317,320,324,326,327,330,331,334,335,337,341,343,346,347,352,355,359,363,364,366,368,371,373,375,378,383,386,390,392,396],[113,33,38,204,114,33],"project\u002Fcritical\u002Fdesign",[192,33,33,206,11,38],"maker\u002Fneutral\u002Fdesign",[208,33,33,209,210,33],"44327623","commenter\u002Fneutral\u002Fdesign","throwawaymaths",[212,33,33,213,214,33],"44326931","other\u002Fneutral\u002Fnone","salviati",[216,33,33,209,217,33],"44330044","Zarathu",[219,33,44,220,95,33],"44334192","project\u002Fpositive\u002Fdesign",[222,33,33,209,223,33],"44338003","lawik",[139,38,45,225,140,33],"project\u002Fneutral\u002Fexecution",[227,38,33,228,229,33],"44324394","commenter\u002Fneutral\u002Fnone","ai-christianson",[143,38,45,225,144,33],[195,38,33,232,11,38],"maker\u002Fneutral\u002Fexecution",[234,235,33,213,236,33],"44324145",2,"s-mon",[238,235,33,213,239,33],"44324218","mikehostetler",[241,235,33,213,242,33],"44324976","rhgraysonii",[244,235,33,213,242,33],"44324986",[157,45,45,246,158,33],"project\u002Fneutral\u002Fperformance",[166,45,33,248,11,38],"maker\u002Fneutral\u002Fperformance",[250,18,33,213,251,33],"44324380","quechimba",[253,18,33,254,11,38],"44325755","maker\u002Fneutral\u002Fnone",[256,44,45,257,258,33],"44325462","project\u002Fneutral\u002Fdesign","arch-choot",[75,44,33,257,11,38],[261,44,45,246,262,33],"44330601","toast0",[264,34,33,213,265,33],"44327403","TheJoeMan",[267,34,33,213,268,33],"44327470","yesco",[270,34,33,213,271,33],"44328225","atmosx",[273,34,33,213,274,33],"44328273","Thaxll",[276,34,33,213,277,33],"44328943","perching_aix",[279,34,33,213,280,33],"44328959","LtdJorge",[282,34,33,213,277,33],"44328985",[284,34,33,213,280,33],"44329166",[286,34,33,213,287,33],"44329242","immibis",[289,34,33,213,262,33],"44330143",[291,34,33,213,287,33],"44331766",[293,34,33,213,262,33],"44332037",[295,34,33,213,280,33],"44331791",[297,34,33,213,277,33],"44334328",[299,31,45,254,300,33],"44324011","jhgg",[302,31,33,254,11,38],"44325781",[304,31,33,213,305,33],"44325832","pdimitar",[307,308,45,309,310,33],"44324563",8,"project\u002Fneutral\u002Fnone","vivzkestrel",[312,308,33,228,313,33],"44325049","lionkor",[315,308,33,213,316,33],"44325338","NooneAtAll3",[318,308,33,213,319,33],"44325368","devoutsalsa",[321,308,33,322,323,33],"44325509","other\u002Fneutral\u002Fprivacy","vjerancrnjak",[325,308,33,322,287,33],"44326328",[60,308,33,254,11,38],[120,328,38,329,121,33],9,"project\u002Fcritical\u002Fexecution",[131,328,45,225,132,33],[332,328,45,333,121,33],"44327185","project\u002Fneutral\u002Fdocs",[124,328,33,232,11,38],[94,32,44,336,95,33],"maker\u002Fpositive\u002Fexecution",[338,189,44,339,340,33],"44323687","project\u002Fpositive\u002Fidea","IlikeKitties",[78,189,33,342,11,38],"maker\u002Fpositive\u002Fdesign",[150,344,45,345,151,33],12,"project\u002Fneutral\u002Fidea",[173,344,33,345,11,38],[348,349,44,350,351,33],"44324125",13,"project\u002Fpositive\u002Fnone","toomuchtodo",[353,354,44,350,239,33],"44324211",14,[356,357,44,350,358,33],"44323853",15,"desireco42",[360,361,44,350,362,33],"44324377",16,"guywithahat",[105,361,33,213,106,33],[365,361,33,228,11,38],"44325678",[367,361,33,228,274,33],"44326953",[369,361,33,228,370,33],"44327350","ricketycricket",[372,361,33,228,287,33],"44329274",[374,361,33,228,106,33],"44414148",[376,361,33,228,377,33],"44331527","sea-gold",[379,380,38,381,382,33],"44327376",17,"project\u002Fcritical\u002Fidea","eatbitseveryday",[384,380,38,381,385,33],"44331040","dewey",[387,388,33,213,389,33],"44324427",18,"arthurcolle",[391,388,38,381,121,33],"44324855",[393,394,33,213,395,33],"44324880",19,"nayuki",[397,394,38,381,313,33],"44325045",[],[400,405,410,415,419,423],{"id":401,"name":402,"points":403,"category":404},"44329457","Nxtscape",314,"productivity",{"id":406,"name":407,"points":408,"category":409},"44351028","Lego Island (isle-portable)",263,"games",{"id":411,"name":412,"points":413,"category":414},"44317012","Claude Code Usage Monitor",245,"dev_tools",{"id":416,"name":417,"points":418,"category":404},"44375761","Scream to Unlock",242,{"id":420,"name":421,"points":422,"category":22},"44318588","rou2exOS",207,{"id":424,"name":425,"points":426,"category":427},"44348448","Idle Reporter",194,"web_saas",false,"v2",{"id":431,"name":5,"line":6,"ai":428,"cat":20,"year":13,"points":14,"comments":15,"rec":28,"s":29,"top":18,"kw":432,"maker":11,"domain":10,"tier":19,"attempts":33,"strip":433,"url":9,"mix":434,"praise":90,"objection":110,"sub":21},44323253,[21,24,25,26,27],"1005330030033000000030300013530550000111",[31,32,33,34],1794036677056]