Loggly middleware for Express.js (server visibility)

Hi!

Oh how long without posting, I’ve been missing it dearly, but in transition between jobs I was super busy, and now I can take the time to add some cool stuff =)

Use Case

I’ve been building an API, it is very cool, but the visibility for it is naturally low compared to websites. Loggly offer a great service for monitoring servers via a simple API available in node.js. While this API is cool, it is super broad and require some experimentation to implement an adequate visibility level.

Wouldn’t be amazing to be able to see every request that come in your server and how it respond? Utopic? Absolutely possible!

Loggly API

Implementation

This implementation has been heavily inspired by Connect logger middleware – which is great.

I deeply recommend you to tune it for your visibility needs, though. Make good use: 

// suggested use:
app.configure(function() {
  app.set("port", process.env.PORT || 3005);
  app.use(logglyMiddleware);
  // ..
  app.use(express.bodyParser());
  app.use(app.router);
  // ..
});

Notes worth taking

  • This snippet will show you information in your console when o development
  • The info sent might be too much in terms of size or frequency, make good use of customization for your needs
  • If you are dealing with a website, I advice you to not send every path hit, it is just too much

Cheers!

CarrierWave – limit file size (plus gif fix)

CarrierWave has an awesome abstraction API. It is simple, clear and extensible. But has some critical vulnerability specially when combined with image processing, such as, ImageMagick when resizing an image will consume exponencial memory size and any upload can easily make your process crash, when not processed safely. Also, it is not pretty good to combine .gif out of the box, because it makes a collection out of the file.

Friendly advice beforehand; Using
http://filepicker.io/
may be a way better idea if you are hosting in Heroku, just make sure if fits your constraints before get hard work done.

Solution Spec

Hard limit file size of the request, so the process don’t block for too long, and don’t blow memory!

If you behind a server such as Apache or Nginx, you can impose a limit to the request size, and you should!

Unless you are in Heroku, and afaik, there is no way to do that, at least just yet. So yes, this can be a major security breach for Rails apps on Heroku.

Given a successful upload, pre-validate size.

The ‘official’ solution attempt to validate the size after the file have been processed. It doesn’t help, since when processing an image rather large (6Mb image consumed 2GB memory in my case) your process will be killed! Letting your website down for some time, and letting your users down as well.

For gifs, take only the first image (less memory consumption too)

When processing .gifs it seems to make a vertical frameset will all the images in the sequence, so it looks like a movie roll, which is not what most people want. Lets just extract the first frame.

Interestingly enough, I found that the processor is invoked for all frames in the .gif. (thanks debugger!)

Solution code

This code takes care the mentioned specs (except for the request size limit), and I think the great advantage is that it avoids opening a file as Image if it fails the size constraint. As well as being very efficient with gifs (only acting on the first frame).
It works on Heroku, with integration for S3, and should work on Amazon Cloud and other VPS.

The shortcome is about handling the exception which is a bit messy involving controller-side logic in a non-automated AR fashion.

Controller

  def create
    begin
    @post = Post.new(params[:post])
    rescue Exception => e
      if e.message == 'too large'
        redirect_to news_path(err: 'file')
      else
        raise e
      end
    end
   #...

uploader

# encoding: utf-8


class NewsUploader < CarrierWave::Uploader::Base

  include CarrierWave::RMagick

  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper


  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def pre_limit file
    #require 'debugger'; debugger
    if file && file.size > 5.megabytes
      raise Exception.new("too large")
    end
    true
  end

  def only_first_frame
    manipulate! do |img|

      if img.mime_type.match /gif/
        if img.scene == 0
          img = img.cur_image #Magick::ImageList.new( img.base_filename )[0]
        else
          img = nil # avoid concat all frames
        end
      end
      img
    end
  end

  version :large, if: :pre_limit do
    process :o nly_first_frame
    process :convert => 'jpg'
    process :resize_to_limit => [1280, 1024]
  end

  # Create different versions of your uploaded files:
  version :small, if: :pre_limit do
    process :o nly_first_frame
    process :convert => 'jpg'
    process :resize_to_limit => [360, 360]
  end


  # For images you might use something like this:
  def extension_white_list
    %w(jpg jpeg gif png)
  end

end

Remove jQTouch + maps lag

Hello!

jQTouch still is a pretty good tool, with performance out-of-the box for old mobiles (being faster then jQMobile), but with some sharp edges.

The problem I deal with in this post may come in a couple of factors, such as:

  • When combined with Google Maps, there is an insane lag when panning (scrolling) the map.
  • General scroll is slow.
  • Some components are slow, particularly when under CSS transition.

At first I thought that either it had a bad interaction with Phonegap, or poor handling of events.

What I find happening that was pretty bad, and almost made me drop it’s use entirely is that it applied some CSS perspective to the body on the bundled apple.css

bad transform

What a bad perspective..

This made the map feel laggy on the Desktop and incredibly bad on iOS!

So, as solution, you have at least 2 options:

1) Remove the property from the .css

2) After jQTouch has been initialized, run a function that remove  the 3D support flag, like so:

$(‘#jqt’).removeClass(‘supports3d’)

Done! =)

Posting a photo (as a business) to a Facebook Page via JavaScript SDK

The Facebook Javascript SDK (API) is not so well documented, what makes not so logical to post to a page, using it. For that I am about to show, make sure your connect scope having at least: “manage_pages,publish_actions,publish_stream”.

I am assuming you already succeeded providing login to the user; if this is not the case, refer to the docs.

We rely heavily on the FB.api method, the docs make a poorly job documenting, but is a starting point anyway. Also, notice the response is async.

Fetch all user pages (actually the first 5k), but only store the first as var page (this is just a sample)

var page = null;
FB.api('/me/accounts', function(response) { console.log(response); page = response.data[0]; })

Now, we want to publish a post to the page timeline, the thing is, we are not posting as ‘me’ anymore, we must post as the page, and it requires both the id and access_token!
I will make a sample function for it, the response is the post id if it all went well, or an error.

function postToPage(page, msg){
  FB.api('/'+page.id+'/feed', 'post', { message: msg, access_token: page.access_token },
    function(res) { console.log(res) }
  )
}
postToPage(page, 'hello fb-page world')

For last, posting a picture requre the url param, like so:

function photoToPage(page, src, msg){
  FB.api('/'+page.id+'/photos', 'post', { url: src, message:msg, access_token: page.access_token },
    function(res) { console.log(res) }
  )
}
photoToPage(page, 'http://24.media.tumblr.com/tumblr_m1ttif5puW1qcrr0lo1_500.png', 'nyan art')

* Don’t try to run all functions in sequence, since the result comes asynchronously you wont have the var page set.

** kudos for Владимир Дворник answer on Stack Overflow for the url param not documented in the Page Graph API.

*** Security note. The JavaScript SDK can be very unsafe in the case a hacker is able to inject JS code in your page (and even happens in Twitter all the time even though they have millions in funding) they may take advantage of all of the user’s permissions.

Done!

ImageMagick on Joyent

It is really simple:


pkgin search ImageMagick # you will get some result like this:
ImageMagick-6.6.6.5 Package for display and interactive manipulation of images
p5-PerlMagick-6.6.6.5 Object-oriented Perl interface to ImageMagick
php53-imagick-5.3.5.2.2.2 Provides a wrapper to the ImageMagick library
ruby18-RMagick-2.13.1nb3 Ruby binding to ImageMagick
ruby18-mini-magick-2.1 Ruby wrapper for ImageMagick command line
ruby19-RMagick-2.13.1nb3 Ruby binding to ImageMagick
ruby19-mini-magick-2.1 Ruby wrapper for ImageMagick command line

Now, install the latest version, today it is 6.6.6.5, so run:

pkgin install ImageMagick-6.6.6.5

Done!

For the Node.js package “imagemagick” at “0.1.2″ works for my use cases, which are just resizes :)
If you are using other languages you may need the other packages as well.

Mongoose validate unique field (insensitive)

Making a validation function for Mongoose (Node.js – MongoDB ODM) that checks upon validation field.

function uniqueFieldInsensitive ( modelName, field ){
	return function(val, cb){
		if( val &amp;&amp; val.length ){ // if string not empty/null
			
			var query = mongoose.models[modelName]
				.where( field, new RegExp('^'+val+'$', 'i') ) // lookup the collection for somthing that looks like this field 
			
			if( !this.isNew ){ // if update, make sure we are not colliding with itself
				query = query.where('_id').ne(this._id)
			}
			
			query.count(function(err,n){
				// false when validation fails
				cb( n &lt; 1 )
			})
		} else { // raise error of unique if empty // may be confusing, but is rightful
			cb( false )
		}
	}
}

Then call it to a field (aka path):

UserSchema.path('nick').validate( uniqueFieldInsensitive('User', 'nick' ), 'unique' )

Recommend you organize all validations in a file for itself, or even a folder if grows too big.

If you have a unique index set for the path you may just save it and check for the error raised; the thing is the format of the error.

Basic Authentication on Node.js – Express and Mongoose

via Axiom Zen

Hello!

This post is about the most important parts I can think of implementing signup and login to Node.js powered by Mongoose and Express.js.

This post have a huge audience, but guys, please keep in mind that this post was done a while ago. It works pretty well as a cook-book, but there probably are better options for achieving this nowadays, new npm packages and such.

Implementing last night, I was impressed on how fast had the functional part done (around 3 hours), pretty much the same time I’d had it done in Rails (if not faster).

Goal:

  • 3 urls: GET login & signup, POST login, POST signup.
  • User fields: email, nick, password(encrypted).
  • Validate (and show) messages for all fields.
I’ve setup a small Github project that may be used as example (assuming you have mongoDB installed and running in localhost) – DOWNLOAD IT FROM GITHUB  

Model: user.js

var Schema = mongoose.Schema
  , ObjectId = Schema.ObjectId
  , Validations = require('./validations.js')
  , salt = 'mySaltyString'
  , SHA2 = new (require('jshashes').SHA512)()

function encodePassword( pass ){
	if( typeof pass === 'string' && pass.length < 6 ) return ''

	return SHA2.b64_hmac(pass, salt )
}

var UserSchema = new Schema({
    nick        : {type: String, required: true, unique: true, trim: true }
  , email       : {type: String, required: true, unique: true, trim: true, lowercase: true }
  , password    : {type: String, set: encodePassword, required: true }
});

UserSchema.statics.classicLogin = function(login, pass, cb) {
	if( login && pass ){
		mongoose.models.User
			.where( 'email', login )
			.where( 'password', encodePassword(pass) )
	  	.findOne( cb )
	} else {
		// just to launch the standard error
		var o = new this({nick: 'VeryUniquejerewelA', password: '', email: login+'aaa'})
		o.save(cb)
	}
}
UserSchema.path('nick').validate( Validations.uniqueFieldInsensitive('User', 'nick' ), 'unique' )
UserSchema.path('email').validate( Validations.uniqueFieldInsensitive('User', 'email' ), 'unique' )
UserSchema.path('email').validate( Validations.emailFormat, 'format' )
UserSchema.path('password').validate( Validations.cannotBeEmpty, 'password' )
UserSchema.plugin( mongoose.availablePlugins.timestamper )

mongoose.model('User', UserSchema)

.Highlights of this code: We are using the package jshashes, which supplies many convenient encryption methods, among those SHA512 –strong enough
It is a good practice to use a salt along, represented by the var salt. In practice it makes way difficult for a cracker that acquired access to the database do decipher the passwords stored.
The method encodePassword is used at two occasions, when setting the User password, and when retrieving it from database.
UserSchema.statics is a object that stores additional static methods our User model will offer.
The function classicLogin requires both login and pass to search the db for existence, otherwise, it will launch an error (kinda of a smelly workaround to make it work dry )
UserSchema.path(…).validate offers us validations, in our case, we do not allow repeated email or nick, and password should be bigger at least 6 characters long. Also email should at least look like a email.
All those validations work along with the own Schema definition: required, unique, trim, lowercase

Route: auth.js

// app.get( '/auth/popover', auth.popover);
exports.popover = function(req, res){
	//req.session.popover = new Date()
	console.log('My session:', req.session)
  res.render('auth/index_pop', req.viewVars);
};

// CLASSIC LOGIN / SIGNUP       --because everyauth seems too messy for login+pass
// app.post('/auth/classic-signup', auth.classicSignup)
exports.classicSignup = function(req,res,next) {
	if( !req.body ){
		console.log('why u signup nobody?')
		return res.redirect('/?nobodySignup')
	}

	var user = new app.models.User()

	user.set('nick', req.body.nick)
	user.set('email', req.body.email)
	user.set('password', req.body.pass)
	user.set('providers', ['signup:'+user.get('email')])
	user.set('profiles', [{ _name: 'signup'}])

	user.save( function(err) {
		if( err ){ // validation failed

			req.viewVars.u = user
			return classicYieldErr( req, res, 'signUp', err)

		} else { // signup successful

			req.session.user = {
				provider: 'signup',
				id: user.get('id'),
				nick: user.get('nick'),
			}

			req.flash('notice', 'Welcome!')
			req.viewVars.welcome_login = "Welcome, "+user.nick

  		res.render('auth/win_pop', req.viewVars )
		}
	})
};

// app.post('/auth/classic-login',  auth.classicLogin)
exports.classicLogin = function(req,res,next) {
	if( !req.body ){
		console.log('why u login nobody?')
		return res.redirect('/?nobodyLogin')
	}

	app.models.User.classicLogin( req.body.email, req.body.pass, function(err, user) {
		if( err ){ // validation failed

			return classicYieldErr( req, res, 'signIn', err)

		} else {

			if( user ){ // login

				req.session.user = {
					provider: 'signup',
					id: user.get('id'),
					nick: user.get('nick'),
				}

				req.flash('notice', 'Welcome!')
				req.viewVars.welcome_login = "Welcome, "+user.nick

	  		res.render('auth/win_pop', req.viewVars )

			} else { // not found
				return classicYieldErr( req, res, 'signIn', {errors:
					{'loginpass': {
						name: 'V',
						path: 'login+password',
						type: 'loginpass'
					}
				}})
			}

		}
	})
};

// display form error
function classicYieldErr( req, res, mode, err ){
	req.viewVars.erroredForm = mode
	if( mode === 'signIn' ){
		req.viewVars.signin_errors = app.helpers.displayErrors( err )
	} else {
		req.viewVars.signup_errors = app.helpers.displayErrors( err )
	}
	req.viewVars.email = req.body.email

	res.render('auth/index_pop', req.viewVars);
}

Here we define the 3 routes;
- one route(GET) that defines one page for both login or signup
- one route(POST) to submit login
- one route(POST) to submit signup
About the last 2, their only role is to allow access for valid data. That is, valid signup data, or login+password existing in our collection from MongoDB.
The function classicYieldErr is there just to serve the errors in sort of an uniform way. We will see about this function on the next file

Model Helper: validations.js

exports.uniqueFieldInsensitive =  function ( modelName, field ){
	return function(val, cb){
		if( val && val.length ){ // if string not empty/null
			// only for new docs
			if( this.isNew ){
				mongoose.models[modelName].where(
					field, new RegExp('^'+val+'$', 'i')
				).count(function(err,n){
					// false when validation fails
					cb( n < 1 )
				})
			} else {
				cb( true )
			}
		} else { // raise error of unique if empty // may be confusing, but is rightful
			cb( false )
		}
	}
}

exports.emailFormat = function( val ){
	// false when validation fails
	return (/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i).test( val )
}

exports.cannotBeEmpty = function( val ){
	console.log('pass val is:', val)

	// not all passwords should be set, BUT when string, should be encoded
	if( typeof val === 'string' ){
		if( val.length ){ // when it comes empty, something went wrong!
			return true
		} else {
			return false
		}
	} else {
		return false
	}
}

This file contains some very important function, being intuitive, I will only comment on the first.
uniqueFieldInsensitive is actually a validation creator. It uses JS’s closure ability along with the powerful this object to wrap the context where this will represent whichever Model is calling it.
The intent of the function is to search the db for any repeated occurrence of the field, case-insensitive. This way the system will block a user “John” from signinup, if “john” is present.

Helper: form_helper.js


//app.helpers.displayErrors = require('./helpers/form_helper.js').displayErrors

stripErrors = function(mongooseErr){
	var prop, list = [];
	for( prop in mongooseErr.errors ){
		list.push( [mongooseErr.errors[prop].path, mongooseErr.errors[prop].type] )
	}
	return list
}

/*
 * Translate mongoose errors into a <li> of errors
 */
exports.displayErrors = function( mongooseErr ){

	console.log( 'mongoose errs', mongooseErr )

	var list = stripErrors( mongooseErr )

	var output = []
	list.forEach(function(e,i){
		switch( e[1] ){
			case( 'unique' ):
				output.push( e[0]+" is taken" )
				break;
			case( 'required' ):
				output.push( e[0]+" is "+e[1] )
				break;
			case( 'format' ):
				output.push( e[0]+" has a bad format" )
				break;
			case( 'password' ):
				output.push( "password should be at least 6 char long" )
				break;
			case( 'loginpass' ):
				output.push( "login+password not found" )
				break;

			default:
				output.push( e[0]+": "+e[1] )
				break;
		}
	})
	if( output.length ){
		// condense all items in an error list
		output = [output.join( '</li><li>\n' )]
		output.unshift( '<ul><li>' )
		output.push( '</li><ul>' )

		// wrap in a div
		output.unshift( "<div class='error block'>" )
		output.push('</div>')
	}
	return output.join('\n')
}

This file provides a translation from Mongoose errors to user-readable errors. In order to offer a good UX, it is important to give accurate feedback. Notice this file could benefit from some refinement :)

Don’t forget to download the code from github, it plays well along everyauth module :)

Cheers!

Read QR code from Javascript and Webcam

Problem

Here, at Flockin we needed a way to login from Browser using a QR-code card and the Webcam.

For the time being (ealy 2012), Javascript have no API to stream/parse from webcam, also the main free library for QR code, Google’s ZXing (actually the only one working I know of) does not support Javascript.

Solution

The most viable solution detected was to parse Webcam from ZXing’s ActionScript module, in a very dry package that could interact with JavaScript through ExternalInterface with Javascript registering a callback.

Use

The use is pretty simple. When the swf object gets completely loaded on the page just register the JS callback which is a function that takes 1 param (String or null), the Interval of call (default 500), and an error callback (default null)

You can download all files from github, that is the project home. *Recommend you adapt the .as3 and recompile to fit your specific needs

CODE

The example below is the same found at the project’s example/index.html

// sample of function that may be registered as Callback.
function actQR( msg ){
	// msg comes null if no code were detected
	if( msg === null ){ //expect a lot of nulls
		console.log("no QR were read at this time")
	} else {
		// a valid QR reading, do something with it
		console.log(msg)
		// ask flash to stop parsing, this saves processing as webcam reading stop
		QR.stop()
	}
}

// sampe of function to be called when something goes wrong
function noWebcam( msg ){
	alert("Err! "+msg)
}

// this setInterval is a safe measure, so we don't call flash function before it is loaded;
var registerQRCb = setInterval(function(){
	//var nomeDoFlash = "QR"
	if( typeof QR === 'object' && QR != null && typeof QR.start === 'function' ){
		clearInterval(registerQRCb)
		// first param is the function signature we want the SWF to call periodicaly
		// second param is the intervall we want it, in miliseconds (default: half-second)
		// third is an signature for callback if something goes wrong, aka, user has no Webcam (default: null)
		QR.start( "actQR", 200, "noWebcam" )
	}
}, 100)

Ruby’s fear-cancer

This video: High Performance Ruby: Threading Versus Evented by Dr Nic Williams, Engine Yard

It meant so much to me!

For around 4 months I’ve been using Node.js, and before that, for 3 years, programming Rails.

As soon as I started on Node.js, I could feel that something was different. My little Computer Science bachelor conscience was starting to tell me: now you are starting to do it right :)

But then, lets go back, Ruby’s syntax is lovely.. Rails API is sugar! But still, it’s neverland. Why??

It does not fit real world! It is a thin layer of happiness, so delicate, that we feel fear of touching it and breaking it. So what we puny humans do? We delegate it to those genius heroes who will be able to take that code and maybe squeeze a few more couples of requests/sec!

But not even that is the cancer I mean.

The cancer here is represented by clown hosting the video. “Oh those scientific articles mess with our head and stuff O.o Let me chew that evil reality and I will give you the RIGHT (sugar coated) solution!” and all other non fun nor assertive statements. By the way, he may be referring to the C10K problem, and alike, articles.

The problem here is, VP  EngineYard and want ppl addicted on his junk. He does not host Node.js.

Ruby always had so many language implementations to solve some important language problems, as well as servers. This is not the first time a good solution for ruby is born (JRuby+Trinidad), but why would they share it before if he could have people paying for so much RAM?

The reason I believe he felt compelled to share it now, is that Node.js unoptimized code can outperform Rails by a LOT,  under 150Mb.

But my main problem is fear of complexity. The host talks about it all over the initial part of the video. He refers his audience under constant fear of it’s own ignorance all the time. This is a awful, and that’s how I felt using Rails. Such a large stack, complex language design, only understanding the framework code itself was hard task.

To keep people in bliss ignorance he just goes like: “Oh I promissed evented? We are past that, right?! HAAAA” so just be happy and keep the status quo. You would’t want to mess your pretty little head with asynchronous code, would you?

I like Node.js, besides performance, language is simple; it is JavaScript, open Objects, closure and more. Of course, don’t assume well-written JS is something easy to do. No great code in any modern language is easy to achieve.

If you’ve developed Rails, you have concepts of MRI, thin, mongrel, jruby, 1.8.7, 1.9.2, rubinius, unicorn, and LOT MORE, whilst in node.js world all that stands for: node.js. It is a unification point for language and server.

What about gems?  npm, a easier system of distributing packages.

Wrapping it up, node.js is no silver bullet, it just made me realize the problems I had while programming ruby, as much as ruby did it for me on php. If nothing else, node.js helped improve ruby’s community by adding options to the web development mainstream.

Would I work with Rails again? If a employer would point me that out as the only chosen solution, then yes, and I’d probably try that stack, but I prefer confidence instead of fear.

When to Ruby on Rails, when to Node.js

(update) Take this post as a naive overview, it may not reflect the most accurate reality

Hello!

I am trying to do a sort of indirect comparison between Rails and Node.js. The very main reason of being indirect, is that Rails is a Framework, while Node.js is an implementation of a programming language with custom libraries.

If it were be to put in a simple phrase, Rails is resourceful and Node.js is light and fast.

Lets elaborate some..

Rails

Is the most complete open-source framework available (that I know of)! Big companies use it. It can do lots of stuff well, in an organized manner; this meaning, Rails is more than just MVC, it has a full stack of features well-integrated, at the same time being very modular. Some of the features included out of the box:

  • Database adapter for the majority of them, supporting plug your own.
  • Database migrations, so multiple dev can sync and experiment with their DB.
  • Powerful engines for Views, Controllers and Models.
  • Support to code generator.
  • Has structure to all sorts of tests and friendly to TDD.
  • Really awesome documentation.
  • Model has all kinds of hooks, validations and associations.
  • Controller has support to handle XML/JSON in the same action that serves HTML.
  • Gems that integrate, for instance, Memcached, MongoDB, Auth and lots more.
So Rails is war-proven, capable of integrating lots of features together without harass. There is also a very cool post of Fabio Akita in the refs. about how it made possible to develop systems in periods before impossible.

Node.js

Two things make this platform suitable for web:

Its engine, V8 is very fast! In a very loose average, 8 times faster than Python (or even up to 200 at peak). Python already outperforms Ruby (ref. bottom)

Second point; and this argument is separated from the above, is that it async-driven (is built around reactor pattern). As in the case, requests can be performed in parallel, without any blocking I/O. A single server can handle a lot. (update) And with >0.6.0 Cluster API, it can scale to use all of available CPU cores.

So, it is a very new sort of backend language, but huge players, besides Joyent, who invented it, are adopting it, including LearnBoost and LinkedIn, which has an awesome article about using. The language, and it’s main web framework, Express, deserve a list of features (you can check more info in the references below).

  • It´s web server is able to handle a HUGE number of connections out of the box
  • Various libraries can be run on browser, the same as in the server
  • Very friendly to Websockets (real-time web apps)
  • Lots of libraries are being ported to it from other langs.
  • Express, inspired in ruby´s Sinatra; is very light on memory but also very powerful
Running a simple benchmark against a single server instance, I were able to get 587 req/s accessing MySQL without any external cache support. This number could scale, if I used Cluster to spawn at least a process per processor.

Summarizing, When to use each?

Rails really shines when..

  • The database is complex in terms of associations.
  • The app structure is well defined.
  • Business rules are complex, and validation is needed.
  • When the number of requests isn´t the a decisive factor.
  • Administrative interfaces.
  • Many developers in parallel keep the DB up-to-date with migrations
  • The database to be used is undefined, or may vary.
What about Node.js?
  • APIs
  • Real-time web/mobile apps.
  • Application that should scale to lots of concurrent requests.
  • Little memory footprint

This being said, there is no reason at all, a web-site or service can´t easily integrate both.

– I’d appreciate if you could leave a comment, either to talk about your case, or add up.

References

 

UPDATE:
http://www.mikealrogers.com/posts/a-new-direction-for-web-applications-.html


http://guides.rubyonrails.org/


http://railscasts.com/


http://blog.heroku.com/archives/2011/6/22/the_new_heroku_2_node_js_new_http_routing_capabilities/


http://nodejs.org/


http://akitaonrails.com/2011/04/16/twitter-muda-de-ruby-para-java-ruby-e-3x-mais-lento-que-java


http://venturebeat.com/2011/08/16/linkedin-node/


http://blog.bossylobster.com/2011/08/lesson-v8-can-teach-python-and-other.html


https://github.com/LearnBoost


http://www.readwriteweb.com/hack/2011/01/how-3-companies-are-using-node.php


https://github.com/LearnBoost/cluster