8 ms·
The Trello Tech Stack
- praxxis 15y ago"We use a really excellent async library" Does anyone happen to know if this is an open source or in house library?
- gecko 15y agoIt's open-source: https://github.com/caolan/async https://github.com/caolan/async
- wildmXranat 15y agoYes, I've seen it on HN before and it's the bee's knees.
- dodger 15y agoI meant to link that. Now it's linked in the post, and it's here: https://github.com/caolan/async https://github.com/caolan/async
- dodger 15y agoFunny story, I found this particular lib the same day as Daniel wrote some code that was an exact drop-in replacement for its 'parallel' function. So he says 'Yes, let's use that one, as I understand and approve of its approach.'
- jeswin 15y agoThe UI could be less cluttered.
- padobson 15y agoI think this is the best write-up I've seen of a full Javascript/CoffeeScript stack. I've always been hesitant to get too far away from my LAPP(ython) stack, but I'll almost certainly be hacking something together with these components to see how I like writing everything in CoffeeScript.
- apg 15y agoThis post raises a few questions for me... and perhaps some one more versed in these stacks can provide answers. - Does the use of CoffeeScript alleviate the MC Escher-esque quality of callbacks within closures involved in working with Javascript on both the server and client (and the data store)? I can totally see the appeal of CoffeeScript's syntax. Giving the programmers something different to look (and learn) at probably provides some cognitive benefit as well. - Is there an acronym/name (ala LAMP) for the Node/MongoDB/Redis stack?
- dodger 15y ago- Daniel is going to write another post detailing this. The answer is that when you combine CoffeeScript and a good async library, you can indeed get rid of that stuff. - MoNsteR? =)
- jeswin 15y agowhen you combine CoffeeScript and a good async library, you can indeed get rid of that stuff My experience has been that you could only do this in few cases. Not an issue that can be worked around elegantly in libraries, you need language support. http://tamejs.org/ http://tamejs.org/
- bluesnowmonkey 15y agoLNMR... um... LaMiNaR? RoMuLaN?
- apg 15y agoI just ran the letters modb-re-nojs-li through my handy word_solver and came up with some candidates: MoRN, NoRM, ModeRN, NiMRod, ReMiNd, MeRLiN, LiMNeR, NiMbLeR
- jeswin 15y ago1. CoffeeScript doesn't alleviate this yet. I doubt will be much progress on this until we find a good way to implement defer/async. https://github.com/jashkenas/coffee-script/issues/350#issuecomment-322321 https://github.com/jashkenas/coffee-script/issues/350#issuec... I am writing a sizable Node app myself. In the end, you just get used to the callback style.
- jslabaugh 15y agoGreat write-up... It made me want to go play with these exact components!
- geekfactor 15y agoDoes anyone know of any open-source projects out there using a similar stack? I'm particularly interested in learning more about client-side view rendering with Backbone and Mustache... server side can be any of Node, Rails or Django.
- jwarzech 15y agoI've been using CoffeScript and backbone.js a lot lately, it really has changed my approach to web apps (keep the server light, just transfer json back and forth). The approach that has worked the best for me is to keep pages such as the landing and authentication as traditional rendered pages and save the client side rendering for the user-authenticated 'meaty' parts of the app. If you want to look a couple really-small examples I have a couple apps on github I used for learning backbone.js/coffeescript. They both use the underscore.js template engine. https://github.com/jwarzech/realtime_hn https://github.com/jwarzech/realtime_hn Backend is sinatra, takes a HN story url and polls the comments in reverse chronological order. https://github.com/jwarzech/inspire_board https://github.com/jwarzech/inspire_board Backend is rails, polls images from dribbble and lets you save your favorites.
- randito 15y agoI like the idea of doing authentication and OpenId in a traditional web stack, while doing the "app" portion in a javascript backbonejs stack. That lets you use existing libraries (Devise, etc.) for the authentication and once that's out of the way, you can go have "fun" with coffeescript and mustache. :)
- karterk 15y agoI have read about various issues in using HAProxy and socket-io (websockets mode). I am currently working on a project that's heading towards that direction - anyone has anything to share on that front?
- feralmoan 15y agonginx supports http1.1 reverse proxying as of a few weeks ago http://wiki.nginx.org/HttpProxyModule http://wiki.nginx.org/HttpProxyModule Mikito Takada (Zendesk) has some really helpful information regarding socket.io + haproxy specific workarounds via http://blog.mixu.net/2011/08/13/nginx-websockets-ssl-and-socket-io-deployment http://blog.mixu.net/2011/08/13/nginx-websockets-ssl-and-soc...
- deleted 15y ago[deleted]
- karterk 15y agoThanks. Looks like it's available only on the development version - I wonder if it's production ready... Also - I took a look at the article - it does not mention using a total node approach of using something like node-http-proxy for load balancing. Any idea on such a set-up? I need HTTPS as well.
- mixu 15y agoA pure-Node approach is a lot simpler: you can just use Node's HTTPS (if you don't care about load balancing) and attach Socket.io to it. Just don't put your Socket.io server behind Nginx if you want WebSockets support. With load balancing, I would recommend going with Stud/Stunnel and HAProxy. Terminating SSL with a specialized piece of software is nicer (separate SSL overhead to another box), and using a separate load balancer allows for more flexible options, e.g. serving static assets from Nginx. There is nothing wrong with node-http-proxy, it's just that these two projects have been around for longer and are better understood from an ops perspective. You cannot use round robin load balancing, you need to have at least IP-based stickiness with Socket.io for now. Well, you can round robin if you use the Redis store but you'll run into inefficiencies with https://github.com/LearnBoost/socket.io/issues/686 https://github.com/LearnBoost/socket.io/issues/686 . I'll do a bit more coverage on other SIO deployment-related issues once I get the chapter on Socket.io finished for my (free) book in a few weeks. If I were starting now, I'd just ignore the Flash sockets transport since it makes the whole stack more complex due to not looking like HTTP to load balancers, and start with Engine.io / WebSocket.io to take advantage of their simplicity.
- DanielBMarkham 15y agoNice job, guys. I love this architecture. This looks a lot like my dream stack for future web work. Would love to hear some more about the "bleeding" experiences you've had.
- dodger 15y agoSocket.io: https://github.com/LearnBoost/socket.io/issues/686 https://github.com/LearnBoost/socket.io/issues/686 MongoDB (on FreeBSD): https://jira.mongodb.org/browse/SERVER-3927 https://jira.mongodb.org/browse/SERVER-3927 Redis: https://github.com/antirez/redis/issues/91 https://github.com/antirez/redis/issues/91 . . . are a few.
- jashkenas 15y agododger: I'd be curious to know where y'all bled over CoffeeScript or Backbone, if you don't mind sharing.
- dodger 15y agoActually, those have been great (and thank you for making them)! We had an outage during beta because somebody forgot to wrap an array comprehension assignment (CoffeeScript) and we didn't test right. Backbone has been really good, and while we had some complaints, I think many have been resolved in more recent versions - we're on something ancient.
- robocat 15y ago> "we're on something ancient" Isn't that one of the major drawbacks of using a bleeding edge Tech Stack? Albeit mitigated by choosing to use code that is easy to comprehend/maintain (like backbone!) What do you think you will do? E.g. With backbone: Merge up, status quo -- maintain your branch, change libraries, or something else?
- dodger 15y ago
- djb_hackernews 15y agoGreat write up. Hopefully that ephemeral data in Redis can scale. They could have used something like Pusher for about half of their implementation (the websockets, message pushing, polling, etc) I bring this up because I built an OSS Pusher clone[1], for those people that want to deploy their own, built on the Play! framework. [1] https://github.com/danbeaulieu/PushPlay https://github.com/danbeaulieu/PushPlay
- jurre 15y agoThere's also this ruby implementation that plays nice with all the pusher libs https://github.com/stevegraham/slanger https://github.com/stevegraham/slanger
- djb_hackernews 15y agoYes, I built my version almost in tandem with Steve. Pusher hosts their js lib on github under the MIT license which made building these things supremely easy.
- swah 15y agoIt seems Socket.io has not had any contenders yet..
- yesbabyyes 15y agoSocket.io is a great library. When it comes to a contender, I see Server-side Events [1] as a contender to WebSockets. I feel it's a simpler architecture which fits HTTP/REST better than WebSockets in the general case. I built a couple of small experiments/examples using CoffeeScript and Redis [2]; the middleware.coffee in particular is designed to be used together with REST, where if you send "Accept: text/event-stream" you will get updates to the resource(s) on that URL. 1: http://dev.w3.org/html5/eventsource/ http://dev.w3.org/html5/eventsource/ 2: https://gist.github.com/1560654 https://gist.github.com/1560654
- josephg 15y agoUnfortunately, eventsource isn't supported by any current version of IE. It'll be awhile before ES can replace your AJAX/websocket libraries. http://caniuse.com/#search=eventsource http://caniuse.com/#search=eventsource
- yesbabyyes 15y agoOn the plus side, it's supported by Opera Mini and iOS. For IE and others (Android, I'm looking at you!), I have yet to try it and so can't vouch for it, but there exists a polyfill: https://github.com/Yaffle/EventSource https://github.com/Yaffle/EventSource
- josephg 15y agoThere are a few, but none of them are widely known about. Socket.io's problems only become visible once you've been working with it for awhile. The three alternatives I know about are SockJS: http://sockjs.org http://sockjs.org Faye - which implements the Bayeux pubsub protocol: http://faye.jcoglan.com/ http://faye.jcoglan.com/ And node-browserchannel (mine) which implements google's browserchannel protocol: https://github.com/josephg/node-browserchannel https://github.com/josephg/node-browserchannel (BrowserChannel works all the way down to IE5.5!)
- sifi 15y agoAwesome job guys. I'm really digging this stack. It is giving me motivation to learn more about Backbone.js
- eaurouge 15y agoIf you could do this over again, would you still choose socket.io for websockets, or would you go with something else like PusherApp?
- dodger 15y agoToday I'd consider going with a service, but first I'd see how https://github.com/LearnBoost/websocket.io https://github.com/LearnBoost/websocket.io looks. Most of our problems have been with abstractions in the socket.io client and scaling issues with server process chatter. The chatter shouldn't be necessary with websockets-only.
- Rauchg 15y agoWith https://github.com/LearnBoost/engine.io https://github.com/LearnBoost/engine.io the abstractions are greatly simplified, which is what I'm announcing today. The socket.io codebase has been shrunk dramatically, and it's as a result easier to scale/maintain.
- deleted 15y ago[deleted]
- dodger 15y agoThat's great!
- jroseattle 15y agoLove the stack, already working on something similar (mine involves nginx, though.) Given we haven't deployed, it's refreshing to see a similar diagram from those already out in front.
- nigma 15y agoVery cool. What do you use for search?
- dodger 15y agoRight now? Just what we can get out of MongoDB. We need better search, and it should be coming soon. Vote it up! https://trello.com/card/board/better-search/4d5ea62fd76aa1136000000c/4e9ec6c79335096aa4658e32 https://trello.com/card/board/better-search/4d5ea62fd76aa113...
- radagaisus 15y agoJust had to share this: Our stack is Redis, MongoDB, Nginx, SCSS, HAML, Coffee, Rails and NodeJS. I'm extremely happy with these choices. Recently me and a friend did a small weekend project: www.bubblefap.com (nsfw) The design and code is a homage to ugliness. We only used PHP-ActiveRecord and that's it. and I had so much fun! I just hacked away! I was cowboy coding, hacking away, and I didn't need to think about frameworks and architecture and integration with fog and hacking Rack to support flash uploads. Oh, good times :-)
- edw519 15y agoUse things that are going to work great in two years. This is one of those remarks that is obvious to someone who knows what it means but mysterious to someone who doesn't. So what does it really mean? - Don't use a technology that, no matter how good, is just too niche for widespread adoption? - Don't use a technology that we'll have trouble finding programmers to support? - Look for stuff that will take better advantage of impending improvements in hardware and communications? - Avoid frameworks for which support may wane? - Avoid technology that we may have to support ourselves? - Avoid anything proprietary whose owner may disappear? - Make sure that whatever you choose, it will work well on mobile technologies, even as native apps? - Choose technologies abstract enough to minimize our costs but not too abstract to be inefficient? - Any combination of the above? - What considerations have I missed?
- jonknee 15y agoI have a feeling that Javascript based NoSQL backed web development is going to be just fine in two years. Quite possibly the standard stack for a large percentage of projects.
- gbog 15y agoI have the opposite feeling. I understand very well the reasons some are pushed away from relational data and data normalization, and set theory formalism. Some are need for change. Some are fears of over engineering. Some are because the trend is to Twitter-like blobs. A big reason is because doing things right is a pain in the... And come the only valid reason, from my POV: We have to denormalize and avoid using the powers of relational data sometime because we do not know how to store (read and write) conveniently huge amounts of relational data; yet. Notice the "yet"? Well, I think it is a technical problem, that may not be so far to find its solution. One example of a solution showing its nose recently: "Google plus with your world". It do strike me that the fact that any query I make to the closest Google server respond /instantly/ to any random word with a join on a very possibly monstruous matrix of all the likes of all my circled users. I don't know how they do store this, where and how they denormalize, but in any case it seems to me to be just "relational data as usual". So in two years, if there is a "bigreldata" software allowing to have a Postgres sitting happily on 1000 T of relational data with instant reads and writes, I would certainly use that with a layer of python glue on the server feeding a slim client than a blob datastore with NoSQL handcuffs and a fat client with 20 libs of third party Javascript code. I may be wrong, however, and would love more insights on this.
- drewda 15y ago"We custom-built a client-side Model cache to handle updates and simplify client-side Model reuse." Is this related at all to backbone.iosync.js?* Or, if not, is it something that Fog Creek will be open to sharing in the future? * https://github.com/logicalparadox/backbone.iobind https://github.com/logicalparadox/backbone.iobind
- jcromartie 15y agoNode.js, Redis, and MongoDB? They've gone full web-scale! In all seriousness, though, it looks like they are using Redis for exactly the right reasons, and the larger architecture is pretty much the definition of a sane forward-looking design.
- wowzer 15y agoWhen I first saw Trello I "felt" that something cool was going on under the hood. So I did a little poking to see what JS technologies you guys were using. The piece I was most excited to learn about was backbone. Had never seen it before and was really impressed by the space it was filling and what it's capable of. Thanks for the write up.
- alexhaefner 15y agoThis is a great write up. We have a very similar stack for a separate team based project we're working on. The only difference is the front end stack, and we have tornado sitting back on the backend to serve http requests when needed. What's the benefit of Mustache/Backbone over just writing your own client side templating, in a practical sense? Last time I used a KVO framework, there was a performance penalty that I did not like. Does Backbone have any performance issues? Or even mustache? What's the trade off of having these frameworks versus generating custom tempting code?
- Smrchy 15y agoI am wondering where and how you terminate the HTTPS connections for websockets. Can you share some details on that?
- trotsky 15y agoHow vulnerable are all javascript approaches in terms of injection type attacks? Do apps like node and mongo effectively prevent them, or is it still possible to shoot yourself in the foot? I've read some off hand comments along the lines of "as long as you're not a total moron you have nothing to worry about", but that sounds a lot like what was said about sql injections and xss before exploiting them went mainstream and it turned out everyones apps were filled with them. Has anyone audited a real world app built with a stack like this and come away with any experience to share?
- brown9-2 15y agoWhat would be the difference in how you would handle this in a single-page JS app like Trello versus a traditional Java/Python/Ruby-based multi-page backend that mostly serves HTML pages? It seems like at the end of the day you still need to validate and sanitize user input before doing anything with it.
- trotsky 15y agoI was inquiring more about the backend js use in node and mongo. You might, for instance, find that simply sanitizing user input isn't enough when you're using the same interpreted language at multiple stages. If an attacker could cause the right front end code to be executed on the app server, or backend code to be executed in the database you could potentially compromise a lot.
- radagaisus 15y agoYou CAN do injections to MongoDB code. An injection is basically 'allow user input to interfere with code' so for mongoDB assuming the query is a string you can do '{name: ' + user_input + '}'. and user_input, without sanitizing it (which is simpler, just converting it to a string) could be: {'$where': ...} http://www.mongodb.org/display/DOCS/Do+I+Have+to+Worry+About+SQL+Injection http://www.mongodb.org/display/DOCS/Do+I+Have+to+Worry+About...
- rjrodger 15y agoUnlike SQL, which you have to build as a string, the natural approach in JavaScript (even for junior devs) is to use an object literal to build the query. And then you get escaping for free.
- techscruggs 15y agoQuestion: They tout MongoDB's "generally fast" read speed. Any idea what this is in relation to? In "fast", are they suggesting that it is faster than a typical RDBMS? If so, does anyone know of any supporting benchmarks or breakdowns of how they accomplish this and to what extent? Its news to me.
- prodigal_erik 15y ago"Client-side MVC" is kind of unfair to backbone.js. I haven't confirmed it myself, but I've seen people explaining how it's also suited to server-side rendering, which means it's not ruled out for competent authors doing progressive enhancement. http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-2-progressive-enhancement-with-backbone-js/ http://lostechies.com/derickbailey/2011/09/26/seo-and-access...
- barmstrong 15y agoGreat writeup! Can you guys share what (if any) test suites were used? Was curious on this point.
- nirvdrum 15y agoThis part caught my eye: "The Socket.io server currently has some problems with scaling up to more than 10K simultaneous client connections when using multiple processes and the Redis store, and the client has some issues that can cause it to open multiple connections to the same server, or not know that its connection has been severed." I wonder if they ran into redis's hard-coded 10k connection upper-limit. As it turns out, their configuration for "unlimited" connections actually has a cap of 10k. I believe in master this is going away, but if you need more than 10k connections on redis <= 2.4, you need to manually patch the daemon, in case anyone else runs into this.
- davesims 15y agoNot to pick on him, because I think the overall received wisdom on new tech has shifted and morphed a great deal over the last few years, no doubt including Joel's...but I can't resist pointing out that, my how times have changed... http://www.joelonsoftware.com/items/2006/09/01.html http://www.joelonsoftware.com/items/2006/09/01.html In other words, it's nice to see Joel greenlight something like this, I'd say it's kind of a sign of the times in terms of the industry's overall comfort level with what would be termed 'hip' technology, or 'new' or whatever moniker you want to attach to it.
- bigiain 15y agoTo Joel's credit, that was over 5 years ago - which is, like, 35 dog-years ago (which are even shorter than tech-years).
- davesims 15y agoAgreed, completely, just pointing out, again, time's is different...
- lrobb 15y agoIt's also weird to see fc have a "get big, then figure out how to make money" mentality.
- skeletonjelly 15y agoSurprised that they didn't incorporate any ASP.NET MVC in there. I was under the impression they were a Microsoft shop?
- sandwiches 15y agoPretty cool; any insight as to how they deploy code to production servers?
- strictfp 15y ago" sending changes to Models down to browser clients". _Down_ to the client? He draws the stack with the client on top and the storage at the bottom, and then says 'down to the client'? I have a collegue who also does this. I never figured out why. Can anyone explain possoble reasoning behind this wording?
- Flenser 15y agoBecause from the client downloads assets and we are more used to thinking about what happens from the client's pov. Alternatively, it could be for the same reason people usually say they're going "up" to a big city, regardless of the direction of travel. The server is the hub and all the clients are down from it. This possibly dates back to when towns/fortifications were usually located on hills.
- roel_v 15y agoBecause the client DOWNloads stuff, presumably. To me it makes perfect sense, servers send stuff 'down' to clients, regardless of a stack figure where stuff is arranged otherwise. Those two are orthogonal.
- crescentfresh 15y agoDoes it just go without saying these days that jQuery is required? Trello uses it, as well as jQuery UI, date.js, and highcharts.js far as I can tell. I mention it because they mention other parts of the client stack (Backbone.js for ex), but not said libs.
- wuher 15y agoGreat writeup, I wish more companies did this: be open about their tech stack and experiences. This inspired me to write about how I think, they could've gone even further: http://wuher-random.blogspot.com/2012/01/single-page-web-apps-and-rest.html http://wuher-random.blogspot.com/2012/01/single-page-web-app...
- dodger 15y agoYep! We intend to use our shiny, well-organized REST API for future development and probably port existing functionality to it, too!