Distributed Tracing with Node JS

The microservice architecture pattern solves many of the problems inherent with monolithic applications. But microservices also bring challenges of their own, one of which is figuring out what went wrong when something breaks. There are at least 3 related challenges here:

  • Log collection
  • Metric collection
  • Distributed tracing

Log and metric collection is fairly straightforward (we’ll cover these in a separate post), but only gets you so far.

Let’s say your 20 microservice application starts behaving badly – you start getting timeouts on a particular API and want to find out why. The first place you look may be your centralized metrics service. This will likely confirm to you that you have a problem, as hopefully you have one or more metrics that are now showing out-of-band numbers.

But what if the issue only affects part of your user population, or worse, a single (but important) customer? In these cases your metrics – assuming you have the right ones in the first place – probably won’t tell you much.

In cases like these, where you have minimal or no guidance from your configured metrics, you start trying to figure out where the problem may be. You know your system architecture, and you’re pretty sure you’ve narrowed the issue down to three or four of your services.

So what’s next? Well, you’ve got your centrally aggregated service logs, right? So you open up three or four windows and try to find an example of a request that fails, and trace it through to the other 2-3 services in the mix. Of course, if your problem only manifests in production then you’ll be sifting through a large number of logs.

How good are you logs anyway? You’re in prod, so you’ve probably disabled debug logs, but even if you hadn’t, logs usually only get you so far. After some digging, you might be able to narrow things down to a function or two, but you’re likely not logging all the information you need to proceed from there. Time to start sifting through code…

But maybe there’s a better way.

Enter Distributed Tracing

Distributed Tracing is a method of tracking a request as it traverses multiple services. Let’s say you have a simple e-commerce app, which looks a little like this (simplified for clarity):

A simplified e-commerce architecture

Now, your user has made an order and wants to track the order’s status. In order for this to happen the user makes a request that hits your API Gateway, which needs to authenticate the request and then send it on to your Orders service. This fetches Order details, then consults your Shipping service to discover shipping status, which in turn calls an external API belonging to your shipping partner.

There are quite a few things that can go wrong here. Your Auth service could be down, your Orders service could be unable to reach its database, your Shipping service could be unable to access the external API, and so on. All you know, though, is that your customer is complaining that they can’t access their Order details and they’re getting aggravated.

We can solve this by tracing a request as it traverses your architecture, with each step surfacing details about what is going on and what (if anything) went wrong. We can then use the Jaeger UI to visualize the trace as it happened, allowing us to debug problems as well as identify bottlenecks.

An example distributed application

To demonstrate how this works I’ve created a distributed tracing example app on Github. The repo is pretty basic, containing a packages directory that contains 4 extremely simple apps: gateway, auth, orders and shipping, corresponding to 4 of the services in our service architecture diagram.

The easiest way to play with this yourself is to simply clone the repo and start the services using docker-compose:

git clone git@github.com:edspencer/tracing-example.git
cd tracing-example
docker-compose up

This will spin up 5 docker containers – one for each of our 4 services plus Jaeger. Now go to http://localhost:5000/orders/12345 and hit refresh a few times. I’ve set the services up to sometimes work and sometimes cause errors – there’s a 20% chance that the auth app will return an error and a 30% chance that the simulated call to the external shipping service API will fail.

After refreshing http://localhost:5000/orders/12345 a few times, open up the Jaeger UI at http://localhost:16686/search and you’ll see something like this:

Jaeger client UI showing traces

http://localhost:5000/orders/12345 serves up the Gateway service, which is a pretty simple one-file express app that will call the Auth service on every request, then make calls to the Orders service. The Orders service in turn calls the Shipping service, which makes a simulated call to the external shipping API.

Clicking into one of the traces will show you something like this:

Details for an individual error trace

This view shows you the the request took 44ms to complete, and has a nice breakdown of where that time was spent. The services are color coded automatically so you can see at a glance how the 44ms was distributed across them. In this case we can see that there was an error in the shipping service. Clicking into the row with the error yields additional information useful for debugging:

Expanded error details

The contents of this row are highly customizable. It’s easy to tag the request with whatever information you like. So let’s see how this works.

The Code

Let’s look at the Gateway service. First we set up the Jaeger integration:

const express = require('express')
const superagent = require('superagent')
const opentracing = require('opentracing')
const {initTracer} = require('jaeger-client')

const port = process.env.PORT || 80
const authHost = process.env.AUTH_HOST || "auth"
const ordersHost = process.env.ORDERS_HOST || "orders"
const app = express()

//set up our tracer
const config = {
serviceName: 'gateway',
reporter: {
logSpans: true,
collectorEndpoint: 'http://jaeger:14268/api/traces',
sampler: {
type: 'const',
param: 1

const options = {
tags: {
'gateway.version': '1.0.0'

const tracer = initTracer(config, options);

The most interesting stuff here is where we declare our config. Here we’re telling the Jaeger client tracer to post its traces to http://jaeger:14268/api/traces (this is set up in our docker-compose file), and to sample all requests – as specified in the sampler config. In production, you won’t want to sample every request – one in a thousand is probably enough – so you can switch to type: ‘probabilistic’ and param: 0.001 to achieve this.

Now that we have our tracer, let’s tell Express to instrument each request that it serves:

//create a root span for every request
app.use((req, res, next) => {
req.rootSpan = tracer.startSpan(req.originalUrl)
tracer.inject(req.rootSpan, "http_headers", req.headers)

res.on("finish", () => {


Here we’re setting up our outer span and giving it a title matching the request url. We encounter 3 of the 4 simple concepts we need to understand:

  • startSpan – creates a new “span” in our distributed trace; this corresponds to one of the rows we see in the Jaeger UI. This span is given a unique span ID and may have a parent span ID
  • inject – adds the span ID somewhere else – usually into HTTP headers for a downstream request – we’ll see more of this in a moment
  • finishing the span – we hook into Express’ “finish” event on the response to make sure we call .finish() on the span. This is what sends it to Jaeger.

Now let’s see how we call the Auth service, passing along the span ID:

//use the auth service to see if the request is authenticated
const checkAuth = async (req, res, next) => {
const span = tracer.startSpan("check auth", {
childOf: tracer.extract(opentracing.FORMAT_HTTP_HEADERS, req.headers)

try {
const headers = {}
tracer.inject(span, "http_headers", headers)
const res = await superagent.get(`http://${authHost}/auth`).set(headers)

if (res && res.body.valid) {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, 200)
} else {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, 401)
} catch(e) {
res.status(503).send("Auth Service gave an error")


There are 2 important things happening here:

  1. We create a new span representing the “check auth” operation, and set it to be the childOf the parent span we created previously
  2. When we send the superagent request to the Auth service, we inject the new child span into the HTTP request headers

We’re also showing how to add tags to a span via setTag. In this case we’re appending the HTTP status code that we return to the client.

Let’s examine the final piece of the Gateway service – the actual proxying to the Orders service:

//proxy to the Orders service to return Order details
app.all('/orders/:orderId', checkAuth, async (req, res) => {
const span = tracer.startSpan("get order details", {
childOf: tracer.extract(opentracing.FORMAT_HTTP_HEADERS, req.headers)
try {
const headers = {}
tracer.inject(span, "http_headers", headers)
const order = await superagent.get(`http://${ordersHost}/order/${req.params.orderId}`).set(headers)
if (order && order.body) {
} else {
span.setTag(opentracing.Tags.HTTP_STATUS_CODE, 200)
res.status(500).send("Could not fetch order")
} catch(e) {
res.status(503).send("Error contacting Orders service")

app.listen(port, () => console.log(API Gateway app listening on port ${port}))

This looks pretty similar to what we just did for the Auth service – we’re creating a new span that represents the call to the Orders service, setting its parent to our outer span, and injecting it into the superagent call we make to Orders. Pretty simple stuff.

Finally, let’s look at the other side of this – how to pick up the trace in another service – in this case the Auth service:

//simulate our auth service being flaky with a 20% chance of 500 internal server error
app.get('/auth', (req, res) => {
const parentSpan = tracer.extract(opentracing.FORMAT_HTTP_HEADERS, req.headers)
const span = tracer.startSpan("checking user", {
childOf: parentSpan, tags: {
[opentracing.Tags.COMPONENT]: "database"

if (Math.random() > 0.2) {
res.json({valid: true, userId: 123})
} else {
span.setTag(opentracing.Tags.ERROR, true)
res.status(500).send("Internal Auth Service error")

Here we see the 4th and final concept involved in distributed tracing:

  • extract – pulls the trace ID from the upstream service from the incoming HTTP headers

This is how the trace is able to traverse our services – in service A we create a span and inject it into calls to service B. Service B picks it up and creates a new span with the extracted span as its parent. We can then pass this span ID on to service C.

Jaeger is even nice enough to automatically create a system architecture diagram for you:

Automatic System Architecture diagram


Distributed tracing is immensely powerful when it comes to understanding why distributed systems behave the way they do. There is a lot more to distributed tracing than we covered above, but at its core it really comes down to those 4 key concepts: starting spans, finishing them, injecting them into downstream requests and extracting them from the upstream.

One nice attribute of open tracing standards is that they work across technologies. In this example we saw how to hook up 4 Node JS microservices with it, but there’s nothing special about Node JS here – this stuff is well supported in other languages like Go and can be added pretty much anywhere – it’s just basic UDP and (usually) HTTP.

For further reading I recommend you check out the Jaeger intro docs, as well as the architecture. The Node JS Jaeger client repo is a good place to poke around, and has links to more resources. Actual example code for Node JS was a little hard to come by, which is why I wrote this post. I hope it helps you in your microservice applications.

A New Stack for 2016: Getting Started with React, ES6 and Webpack

A lot has changed in the last few years when it comes to implementing applications using JavaScript. Node JS has revolutionized how many of us create backend apps, React has become a widely-used standard for creating the frontend, and ES6 has come along and completely transformed JavaScript itself, largely for the better.

All of this brings new capabilities and opportunities, but also new challenges when it comes to figuring out what’s worth paying attention to, and how to learn it. Today we’ll look at how to set up my personal take on a sensible stack in this new world, starting from scratch and building it up as we go. We’ll focus on getting to the point where everything is set up and ready for you to create the app.

The stack we’ll be setting up today is as follows:

  • React – to power the frontend
  • Babel – allows us to use ES6 syntax in our app
  • Webpack – builds our application files and dependencies into a single build

Although we won’t be setting up a Node JS server in this article, we’ll use npm to put everything else in place, so adding a Node JS server using Express or any other backend framework is trivial. We’re also going to omit setting up a testing infrastructure in this post – this will be the subject of the next article.

If you want to get straight in without reading all the verbiage, you can clone this github repo that contains all of the files we’re about to create.

Let’s go

The only prerequisite here is that your system has Node JS already installed. If that isn’t the case, go install it now from http://nodejs.org. Once you have Node, we’ll start by creating a new directory for our project and setting up NPM:

mkdir myproject
npm init

The npm init command takes you through a short series of prompts asking for information about your new project – author name, description, etc. Most of this doesn’t really matter at this stage – you can easily change it later. Once that’s done you’ll find a new file called package.json in your project directory.

Before we take a look at this file, we already know that we need to bring in some dependencies, so we’ll do that now with the following terminal commands:

npm install react –save
npm install react-dom –save
npm install webpack –save-dev

Note that for the react dependency we use –save, whereas for webpack we use –save-dev. This indicates that react is required when running our app in production, whereas webpack is only needed while developing (as once webpack has created your production build, its role is finished). Opening our package.json file now yields this:

   "name": "myproject",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
       "test": "echo \"Error: no test specified\" && exit 1"
   "author": "",
   "license": "ISC",
   "dependencies": {
     "react": "^0.14.7",
     "react-dom": "^0.14.7"
   "devDependencies": {
     "webpack": "^1.12.14"

This is pretty straightforward. Note the separate dependencies and devDependencies objects in line with our –save vs –save-dev above. Depending on when you created your app the version numbers for the dependencies will be different, but the overall shape should be the same.

We’re not done installing npm packages yet, but before we get started with React and ES6 we’re going to get set up with Webpack.

Setting up Webpack

We’ll be using Webpack to turn our many application files into a single file that can be loaded into the browser. As it stands, though, we don’t have any application files at all. So let’s start by creating those:

mkdir src
touch src/index.js
touch src/App.js

Now we have a src directory with two empty files. Into App.js, we’ll place the following trivial component rendering code:

var App = function() {
  return "<h1>Woop</h1>";

module.exports = App;

All we’re doing here is returning an HTML string when you call the App function. Once we bring React into the picture we’ll change the approach a little, but this is good enough for now. Into our src/index.js, we’ll use:

var app = require('./App');

So we’re simply importing our App, running it and then writing the resulting HTML string into the DOM. Webpack will be responsible for figuring out how to combine index.js and App.js and building them into a single file. In order to use Webpack, we’ll create a new file called webpack.config.js (in the root directory of our project) with the following contents:

var path = require('path');
var webpack = require('webpack');

module.exports = {
  output: {
    filename: 'bundle.js'
  entry: [

This really couldn’t be much simpler – it’s just saying take the entry point (our src/index.js file) as input, and save the output into a file called bundle.js. Webpack takes those entry file inputs, figures out all of the require(‘…’) statements and fetches all of the dependencies as required, outputting our bundle.js file.

To run Webpack, we simply use the `webpack` command in our terminal, which will do something like this:


webpack terminal output

As we can see, we now have a 1.75kb file called bundle.js that we can serve up in our project. That’s a little heavier than our index.js and App.js files combined, because there is a little Webpack plumbing that gets included into the file too.

Now finally we’ll create a very simple index.html file that loads our bundle.js and renders our app:

    <meta charset="utf-8">
    < div id="main"></div>
    < script type="text/javascript" src="bundle.js" charset="utf-8"></script>

Can’t get much simpler than that. We don’t have a web server set up yet, but we don’t actually need one. As we have no backend we can just load the index.html file directly into the browser, either by dragging it in from your OS’s file explorer program, or entering the address manually. For me, I can enter file:///Users/ed/Code/myproject/index.html into my browser’s address bar, and be greeted with the following:


Our first rendered output

Great! That’s our component being rendered and output into the DOM as desired. Now we’re ready to move onto using React and ES6.

React and ES6

React can be used either with or without ES6. Because this is the future, we desire to use the capabilities of ES6, but we can’t do that directly because most browsers currently don’t support it. This is where babel comes in.

Babel (which you’ll often hear pronounced “babble” instead of the traditional “baybel”) a transpiler, which takes one version of the JavaScript language and translates it into another. In our case, it will be translating the ES6 version of JavaScript into an earlier version that is guaranteed to run in browsers. We’ll start by adding a few new npm package dependencies:

npm install babel-core –save-dev
npm install babel-loader –save-dev
npm install babel-preset-es2015 –save-dev
npm install babel-preset-react –save-dev
npm install babel-plugin-transform-runtime –save-dev

npm install babel-polyfill –save
npm install babel-runtime –save

This is quite a substantial number of new dependencies. Because babel can convert between many different flavors of JS, once we’ve specified the babel-core and babel-loader packages, we also need to specify babel-preset-es2015 to enable ES6 support, and babel-preset-react to enable React’s JSX syntax. We also bring in a polyfill that makes available new APIs like Object.assign that babel would not usually bring to the browser as it requires some manipulation of the browser APIs, which is something one has to opt in to.

Once we have these all installed, however, we’re ready to go. The first thing we’ll need to do is update our webpack.config.js file to enable babel support:

var path = require('path');
var webpack = require('webpack');

module.exports = {
  module: {
    loaders: [
        loader: "babel-loader",
        // Skip any files outside of your project's `src` directory
        include: [
          path.resolve(__dirname, "src"),
        // Only run `.js` and `.jsx` files through Babel
        test: /\.jsx?$/,
        // Options to configure babel with
        query: {
          plugins: ['transform-runtime'],
          presets: ['es2015', 'react'],
  output: {
    filename: 'bundle.js'
  entry: [

Hopefully the above is clear enough – it’s the same as last time, with the exception of the new module object, which contains a loader configuration that we’ve configured to convert any file that ends in .js or .jsx in our src directory into browser-executable JavaScript.

Next we’ll update our App.js to look like this:

import React, {Component} from 'react';

class App extends Component {
  render() {
    return (<h1>This is React!</h1>);
export default App;

Cool – new syntax! We’ve switched from require(”) to import, though this does essentially the same thing. We’ve also switched from `module.exports = ` to `export default `, which is again doing the same thing (though we can export multiple things this way).

We’re also using the ES6 class syntax, in this case creating a class called App that extends React’s Component class. It only implements a single method – render – which returns a very similar HTML string to our earlier component, but this time using inline JSX syntax instead of just returning a string.

Now all that remains is to update our index.js file to use the new Component:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById("main"));

Again we’re using the import syntax to our advantage here, and this time we’re using ReactDOM.render instead of document.write to place the rendered HTML into the DOM. Once we run the `webpack` command again and refresh our browser window, we’ll see a screen like this:


Now we’re cooking with gas. Or, at least, rendering with React

Next Steps

We’ll round out by doing a few small things to improve our workflow. First off, it’s annoying to have to switch back to the terminal to run `webpack` every time we change any code, so let’s update our webpack.config.js with a few new options:

module.exports = {
  //these remain unchanged
  module: {...},
  output: {...},
  entry: [...],

  //these are new
  watch: true,
  colors: true,
  progress: true

Now we just run `webpack` once and it’ll stay running, rebuilding whenever we save changes to our source files. This is generally much faster – on my 2 year old MacBook Air it takes about 5 seconds to run `webpack` a single time, but when using watch mode each successive build is on the order of 100ms. Usually this means that I can save my change in my text editor, and by the time I’ve switched to the browser the new bundle.js has already been created so I can immediately refresh to see the results of my changes.

The last thing we’ll do is add a second React component to be consumed by the first. This one we’ll call src/Paragraph.js, and it contains the following:

import React, {Component} from 'react';

export default class Paragraph extends Component {
  render() {
    return (<p>{this.props.text}</p>);

This is almost identical to our App, with a couple of small tweaks. First, notice that we’ve moved the `export default` inline with the class declaration to save on space, and then secondly this time we’re using {this.props} to access a configured property of the Paragraph component. Now, to use the new component we’ll update App.js to look like the following:

import React, {Component} from 'react';
import Paragraph from './Paragraph';

export default class App extends Component {
  render() {
    return (
      < div className="my-app">
        <h1>This is React!!!</h1>
        <Paragraph text="First Paragraph" />
        <Paragraph text="Second Paragraph" />

Again a few small changes here. First, note that we’re now importing the Paragraph component and then using it twice in our render() function – each time with a different `text` property, which is what is read by {this.props.text} in the Paragraph component itself. Finally, React requires that we return a single root element for each rendered Component, so we wrap our <h1> and <Paragraph> tags into an enclosing <div>

By the time you hit save on those changes, webpack should already have built a new bundle.js for you, so head back to your browser, hit refresh and you’ll see this:


The final rendered output

That’s about as far as we’ll take things today. The purpose of this article was to get you to a point where you can start building a React application, instead of figuring out how to set up all the prerequisite plumbing; hopefully it’s clear enough how to continue from here.

You can find a starter repository containing all of the above over on GitHub. Feel free to clone it as the starting point for your own project, or just look through it to see how things fit together.

In the next article, we’ll look at how to add some unit testing to our project so that we can make sure our Components are behaving as they should. Until then, happy Reacting!

Jasmine and Jenkins Continuous Integration

I use Jasmine as my JavaScript unit/behavior testing framework of choice because it’s elegant and has a good community ecosystem around it. I recently wrote up how to get Jasmine-based autotesting set up with Guard, which is great for development time testing, but what about continuous integration?

Well, it turns out that it’s pretty difficult to get Jasmine integrated with Jenkins. This is not because of an inherent problem with either of those two, it’s just that no-one got around to writing an open source integration layer until now.

The main problem is that Jasmine tests usually expect to run in a browser, but Jenkins needs results to be exposed in .xml files. Clearly we need some bridge here to take the headless browser output and dump it into correctly formatted .xml files. Specifically, these xml files need to follow the JUnit XML file format for Jenkins to be able to process them. Enter guard-jasmine.


In my previous article on getting Jasmine and Guard set up, I was using the jasmine-headless-webkit and guard-jasmine-headless-webkit gems to provide the glue. Since then I’ve replaced those 2 gems with a single gem – guard-jasmine, written by Michael Kessler, the Guard master himself. This simplifies our dependencies a little, but doesn’t buy us the .xml file functionality we need.

For that, I had to hack on the gem itself (which involved writing coffeescript for the first time, which was not a horrible experience). The guard-jasmine gem now exposes 3 additional configurations:

  • junit – set to true to save output to xml files (false by default)
  • junit_consolidate – rolls nested describes up into their parent describe blocks (true by default)
  • junit_save_path – optional path to save the xml files to

The JUnit Xml reporter itself borrows heavily from larrymyers‘ excellent jasmine-reporters project. Aside from a few changes to integrate it into guard-jasmine it’s the same code, so all credit goes to to Larry and Michael.

Sample usage:

In your Guardfile:

guard :jasmine, :junit => true, :junit_save_path => 'reports' do
  watch(%r{^spec/javascripts/.+$}) { 'spec/javascripts' }
  watch(%r{^spec/javascripts/fixtures/.+$}) { 'spec/javascripts' }
  watch(%r{^app/assets/javascripts/(.+?)\.(js\.coffee|js|coffee)(?:\.\w+)*$}) { 'spec/javascripts' }

This will just run the full set of Jasmine tests inside your spec/javascripts directory whenever any test, source file or asset like CSS files change. This is generally the configuration I use because the tests execute so fast I can afford to have them all run every time.

In the example above we set the :junit_save_path to ‘reports’, which means it will save all of the .xml files into the reports directory. It is going to output 1 .xml file for each Jasmine spec file that is run. In each case the name of the .xml file created is based on the name of the top-level `describe` block in your spec file.

To test that everything’s working, just run `bundle exec guard` as you normally would, and check to see that your `reports` folder now contains a bunch of .xml files. If it does, everything went well.

Jenkins Settings

Once we’ve got the .xml files outputting correctly, we just need to tell Jenkins where to look. In your Jenkins project configuration screen, click the Add Build Step button and add a “Publish JUnit test result report” step. Enter ‘reports/*.xml’ as the `Test report XMLs` field.

If you’ve already got Jenkins running your test script then you’re all done. Next time a build is triggered the script should run the tests and export the .xml files. If you don’t already have Jenkins set up to run your tests, but you did already set up Guard as per my previous article, you can actually use the same command to run the tests on Jenkins.

After a little experimentation, people tend to come up with a build command like this:

bash -c ' bundle install --quiet \
&& bundle exec guard '

If you’re using rvm and need to guarantee a particular version you may need to prepend an `rvm install` command before `bundle install` is called. This should just run guard, which will dump the files out as expected for Jenkins to pick up.

To clean up, we’ll just add a second post-build action, this time choosing the “Execute a set of scripts” option and entering the following:

kill -9 `cat guard.pid`

This just kills the Guard process, which ordinarily stays running to power your autotest capabilities. Once you run a new build you should see a chart automatically appear on your Jenkins project page telling you full details of how many tests failed over time and in the current build.

Getting it

Update: The Pull Request is now merged into the main guard-jasmine repo so you can just use `gem ‘guard-jasmine’` in your Gemfile

This is hot off the presses but I wanted to write it up while it’s still fresh in my mind. At the time of writing the pull request is still outstanding on the guard-jasmine repository, so to use the new options you’ll need to temporarily use my guard-jasmine fork. In your Gemfile:

gem 'guard-jasmine'

Once the PR is merged and a new version issued you should switch back to the official release channel. It’s working well for me but it’s fresh code so may contains bugs – YMMV. Hopefully this helps save some folks a little pain!

Sencha Con 2013 Wrapup

So another great Sencha Con is over, and I’m left to reflect on everything that went on over the last few days. This time was easily the biggest and best Sencha Con that I’ve been to, with 800 people in attendance and a very high bar set by the speakers. The organization was excellent, the location fun (even if the bars don’t open until 5pm…), and the enthusiasm palpable.

I’ve made a few posts over the last few days so won’t repeat the content here – if you want to see what else happened check these out too:

What I will do though is repeat my invitation to take a look at what we’re doing with JavaScript at C3 Energy. I wrote up a quick post about it yesterday and would love to hear from you – whether you’re at Sencha Con or not.

Now on to some general thoughts.


There was a large range in the technical difficulty of the content, with perhaps a slightly stronger skew up the difficulty chain compared to previous events. This is a good thing, though there’s probably still room for more advanced content. Having been there before though, I know how hard it is to pitch that right so that everyone enjoys and gets value of out it.

The biggest challenge for me was the sheer number of tracks – at any one time there would be seven talks happening simultaneously, two or three of which I’d really want to watch. Personally I’d really love it if the hackathon was dropped in favor of a third day of sessions, with a shift down to 4-5 tracks. I’m sure there’s a cost implication to that, but it’s worth thinking about.


There were cameras set up in at least the main hall on the first day, but I didn’t see any on day 2. I did overhear that the video streams were being recorded directly from what was being shown on the projectors, with the audio recorded separately. If that’s true I’d guess it would make editing a bit easier so maybe that’ll means a quick release.

Naturally, take this with a pinch of salt until the official announcement comes out. In the meantime, there’s at least one video available so far:

Grgur lets off some steam

Grgur lets off some steam

Fun Things

The community pavilion was a great idea, and served as the perfect space for attendees with hang out away from the other rascals running around the hotel. Coffee and snacks were available whenever I needed them, and there was plenty of seating to chill out in.

I missed out on the visit to the theme park, which I hear was by far the most fun part of the event. Having a theme park kick out everyone but Sencha Con attendees while serving copious amounts of alcohol seemed to go down very well with the attendees!


I had been hoping to give a presentation on the new C3UI framework at the unconference, but unfortunately there were no projectors available at that part of the event. My outrageous presentation style tends to require a projector and a stage to stomp around on so that was a no-go for me.

Maybe next time a lightning talk track alongside the unconference would be a good addition. So long as there is a projector 🙂

All in all, what a fantastic event. Can’t wait for next year.

Sencha Con Attendees: I Need You

Love working with Sencha frameworks? Want to come work with me on the next generation? I moved on to C3 Energy about a year ago, where we are busily building the operating system for the largest machine ever conceived by humans – the Smart Grid.

The Smart Grid is an amazing concept that’s being rolled out right now. C3 Energy is the only company in existence that addresses the full stack of Smart Grid architecture – from generation through transmission and end-user consumption.

But what’s that got to do with JavaScript? Well, my team gets to work on building the UI that powers everything that happens on the smart grid. We have some unique requirements that have led us to write our own beautiful little framework, optimized for end-user performance and developer productivity. Naturally, this leaves me feeling like this:

Success Kid

We’re a small (70 person) company of exceptionally talented people. We have a staggeringly successful collection of people both on the board and as the executive team.

We’d like to attract more people like us, and the Sencha community is the perfect place to look – especially given how much the framework has been inspired by what I helped create at Sencha.

If you’re intrigued but don’t know much about this space, I can’t recommend this video enough. This is a presentation our CEO Tom Siebel gave a few months back, introducing why the company exists, which problems it’s solving, and why we’re doing what we’re doing. If you can watch this without getting excited, this probably isn’t for you 🙂


You’ll get to work alongside people like this every day at C3. It’s really an incomparable feeling, and I’d love to introduce you to it. If you’re interested in finding out more in a low pressure way, drop me a comment or a tweet (@edspencer) or come grab me so I can buy you a beer.

Sencha Con 2013: Ext JS Performance tips

Just as with Jacky’s session, I didn’t plan on making a separate post about this, but again the content was so good and I ended up taking so many notes that it also warrants its own space. To save myself from early carpal tunnel syndrome I’m going to leave this one in more of a bullet point format.


Ext JS has been getting more flexible with each release. You can do many more things with it these days than you used to be able to, but there has been a performance cost associated with that. In many cases this performance degradation is down to the way the framework is being used, as opposed to a fundamental problem with the framework itself.

There’s a whole bunch of things that you can do to dramatically speed up the performance of an app you’re not happy with, and Nige “Animal” White took us through them this morning. Here’s what I was able to write down in time:

Slow things

Nige identified three of the top causes of sluggish apps, which we’ll go through one by one:

  • Network latency
  • JS execution
  • Layout activity

Network latency:

  • Bad ux – got to stare at blank screen for a while
  • Use Sencha Command to build the app – single file, minimized
  • 4810ms vs 352ms = dynamic loading vs built

JavaScript execution:

  • Avoid slow JS engines (he says with a wry smile)
  • Optimize repeated code – for loops should be tight, cache variables outside
  • Ideally, don’t do any processing at render time
  • Minimize function calls
  • Lazily instantiate items
  • Use the PageAnalyzer (in the Ext JS SDK examples folder) to benchmark your applications
  • Start Chrome with –enable-benchmarking to get much more accurate timing information out of the browser


Suspend store events when adding/removing many records. Otherwise we’re going to get a full Ext JS layout pass for each modification

 //do lots of updating

Ditto on trees (they’re the same as grids)
Coalesce multiple layouts. If you’re adding/removing a bunch of Components in a single go, do it like this:

 //do a bunch of UI updates

Container#add accepts an array of items, which is faster than iterating over that array yourself and calling .add for each one. Avoid layout constraints where possible – in box layouts, align: ‘stretchmax’ is slow because it has to do multiple layout runs. Avoid minHeight, maxHeight, minWidth, maxWidth if possible

At startup:

  • Embed initialization data inside the HTML if possible – avoids AJAX requests
  • Configure the entire layout in one shot using that data
  • Do not make multiple Ajax requests, and build the layout in response

Use the ‘idle’ event

  • Similar to the AnimationQueue
  • Ext.globalEvents.on(‘idle’, myFunction) – called once a big layout/repaint run has finished
  • Using the idle listener sometimes preferable to setTimeout(myFunction, 1), because it’s synchronous in the same repaint cycle. The setTimeout approach means the repaint happens, then your code is called. If your code itself requires a repaint, that means you’ll have 2 repaints in setTimeout vs 1 in on.(‘idle’)

Reduce layout depth

Big problem – overnesting. People very often do this with grids:

    xtype: 'tabpanel',
    items: [
            title: 'Results',
            items: {
                xtype: 'grid'


    xtype: 'tabpanel',
    items: {
        title: 'Results',
        xtype: 'grid'

This is important because redundant components still cost CPU and memory. Everything is a Component now – panel headers, icons, etc etc. Can be constructing more Components than you realize. Much more flexible, but easy to abuse

Lazy Instantiation

New plugin at https://gist.github.com/ExtAnimal/c93148f5194f2a232464

    xtype: 'tabpanel',
    ptype: 'lazyitems',
    items: {
        title: 'Results',
        xtype: 'grid'

Overall impact

On a real life large example contributed by a Sencha customer:

Bad practices: 5187ms (IE8)
Good practices: 1813ms (IE8)
1300ms vs 550ms on Chrome (same example)

Colossal impact on the Ext.suspendLayout example – 4700ms vs 100ms on Chrome


This is definitely a talk you’ll want to watch when they go online. It was absolutely brimming with content and the advice comes straight from the horse’s mouth. Nige did a great job presenting, and reminded us that performance is a shared responsibility – the framework is getting faster as time goes by, but we the developers need to do our share too to make sure it stays fast.

Sencha Con 2013: Fastbook

I didn’t plan on writing a post purely on Fastbook, but Jacky’s presentation just now was so good I felt it needed one. If you haven’t seen Fastbook yet, it is Sencha’s answer to the (over reported) comments by Zuckerburg that using HTML5 for Facebook’s mobile app was a mistake.

Jacky on stage

After those comments there was a lot of debate around whether HTML5 is ready for the big time. Plenty of opinions were thrown around, but not all based on evidence. Jacky was curious about why Facebook’s old app was so slow, and wondered if he could use the same technologies to achieve a much better result. To say he was successful would be a spectacular understatement – Fastbook absolutely flies.

Performance can be hard to describe in words, so Sencha released this video that demonstrates the HTML5 Fastbook app against the new native Facebook apps. As you can see, not only is the HTML5 version at least as fast and fluid as the native versions, in several cases it’s actually significantly better (especially on Android).


The biggest challenge here is dynamically loading and scrolling large quantities of data while presenting a 60fps experience to the user. 60fps means you have just 16.7ms per frame to do everything, which is a hugely tall order on a CPU and memory constrained mobile device.

The way to achieve this is to treat the page as an app rather than a traditional web page. This means we need to be a lot more proactive in managing how and when things are rendered – something that traditionally has been in the domain of the browser’s own rendering and layout engines. Thankfully, the framework will do all of this for you.

As an example, Jacky loaded up Gmail’s web app and showed what happens when you scroll a long way down your inbox. The more you scroll, the more divs are added to the document (one new div per message). Each div contains a bunch of child elements too, so we’re adding maybe a dozen or so nodes to our DOM tree per message.

The problem with this is that as the DOM tree gets larger and larger, everything slows down. You could see the inspector showing slower and slower layout recalculations, making the app sluggish.

The solution is to recycle DOM nodes once they’re no longer visible. In this way, a list that seems to have infinite content could contain only say 10 elements – just enough to fill the screen. Once you scroll down the list, DOM nodes that scrolled off the top are detached, updated with new data and placed at the bottom of the list. Simple. Ingenius. Beautiful.


There’s usually a lot more going on in an app than just animating a scrolling view though. There’s data to load via AJAX, images to load, compositing, processing, and whatever else your app needs to do. And then there are touch events, which need to feel perfectly responsive at all times, even while all of this is going on.

To make this sane and manageable, we have a new class called AnimationQueue. All of the jobs I just mentioned above – handling touch events, animation, network requests and so on – are dispatched through the AnimationQueue with a given priority. Touch event handling has the top priority, followed by animation, followed by everything else.

AnimationQueue does as much as it can in that 16.7ms window, then breaks execution again to allow the browser to reflow/repaint/whatever else it needs to do. What this means is that while scrolling down a large list, it’s likely that our CPU/GPU is being taxed so much that we don’t have any time to load images or other low priority jobs.

This is a Good Thing, because if we’re scrolling through a large list there’s a good chance we are going to skip right over those images anyway. In the end they’re loaded as soon as the AnimationQueue has some spare time, which is normally when your scrolling of the list has slowed down or stopped.


The final, and most complex technique Jacky discussed was Sandboxing. The larger your application gets, the larger the DOM tree. Even if you are using best practices, there’s an expense to simply having so many components on the same page. The bottleneck here is in the browser itself – looks like we need another hack.

To get around this, we can dynamically create iframes that contain parts of our DOM tree. This way our main page DOM tree can remain small but we can still have a huge application. This not only speeds up browser repaint and reflow, it also improves compositing performance, DOM querying and more.

This all happens under the covers and Jacky’s aiming on including Ext.Sandbox in Sencha Touch 2.3 so that all apps can take advantage of this huge improvement. He cautioned (rightly) that it’ll only make 2.3 if it’s up to his high standards though, so watch this space.

Sencha Con 2013 Day 1

Sencha Con 2013 kicked off today, with some stunning improvements demoed across the product set. I’m attending as an audience member for the first time so thought I’d share how things look from the cheap seats.


The keynote was very well put together, with none of the AV issues that plagued us last year (maybe they seemed worse from behind the curtain!). It started off with a welcome from Paul Kopacki, followed by some insights into the current status of developers in the world of business (apparently we’re kingmakers – who knew!). One of Blackberry’s evangelists came up and made a pretty good pitch for giving them a second look (the free hardware probably helped a little…)

The meat, though, was in the second half of the presentation. We were treated to a succession of great new features across Ext JS, Sencha Touch and Sencha Architect, which I’ll go into in a little more detail below.

But it was Abe Elias and Jacky Nguyen who stole the show in the end. Unleashing a visionary new product, Sencha Space, they demonstrated a brand new way to enable businesses to elegantly solve the problem of BYOD (Bring Your Own Device).

Nobody wants to be given a mobile phone by their IT department when they’ve got a brand new iPhone in their pocket. But those IT guys have good reason for doing this – consumer browsers are currently inherently insecure. Sencha Space solves this problem by providing a single app that employees can install, log in to and gain access to all of the apps needed to be productive in the company.

I could write a lot more about it but the 2 minute video below can surely do a better job:

Ext JS upgrades

The keynote lasted most of the morning, but in the afternoon Don Griffin came back on stage to tell us more about what’s coming soon in Ext JS. Don heads up Ext JS these days, and is one of the most intelligent and experienced people I’ve had the joy of working with. I’m pretty sure he gained the largest amount of spontaneous applause of the day during the Ext JS talk, which is no surprise given the awesome stuff he showed us.

I forget which order things were revealed in, but these things stood out for me:

  • Touch Support – while this may seem anathema to the thinking behind Ext JS, it’s an undeniable fact that people try to use Ext JS applications on tablets. Whether they should or not is a different question, but in this next release it will be officially supported by the framework. Momentum scrolling, pinch to zoom and dragdrop resizing are all supported at your fingertips.
  • Grid Gadgets – quite likely the coolest new feature, Gadgets allow you to render any Component into each cell in a Grid, in an extremely CPU and memory efficient manner. Seeing a live grid updating with rich charts and other widgets at high frequency was a fantastic experience
  • Border Layout – allows your users to rearrange the border layouts used in your apps with drag and drop. Easy to switch between accordion layout, box layout or tabs
  • A shedload more. The enforced pub crawl has temporarily relieved me of a full memory. So impressed with everything that was demonstrated today.

Sencha Touch upgrades

Jacky came up and delivered a presentation on what’s coming up in Sencha Touch, using his idiosyncratic and inimitable style. Some of the things that stood out for me:

  • Touch gets a grid. It performs really well and looks great. Good for (sparing) use on tablet apps
  • XML configs. Not sure how I feel about this yet, but ST 2.3 will allow for views to be declared in XML, which is transformed into the normal JSON format under the covers. You end up writing few lines of code, but the overall file size probably doesn’t change too much. With a decent editor the syntax highlighting definitely makes the View code easier to read though
  • ViewModel. Just as we have Ext.data.Model for encapsulating data models, we now have ViewModel for encapsulating a view model, which includes things like state. Leads to a much improved API for updating Views in response to other changes
  • Theming. 2 additional themes were added, and the others have all been refactored to make theming even easier

Again there’s a lot more here and I couldn’t possibly do it all justice in a blog post. It’s geniunely thrilling to see these young frameworks mature into stellar products that are being used by literally millions of developers. Very exciting.

Architect upgrades

Architect has come a really long way since its inception a couple of years ago. The new features introduced today looked like some of the largest steps forward the product has ever taken. I’m finally getting close to actually thinking about using it in real life (I’m a glutten for editing code in Sublime Text). Some standout features:

  • New template apps to get you up and running with a new app in seconds
  • Integration with Appurify, which allows you to test your Architect apps on real devices hosted by their service
  • Allows you to install third party extensions into Architect, and have them seamlessly integrated into your project

Day 1 Summary

Although I worked with these people for years, somehow I’m still surprised when I see every single developer giving world class presentations. I don’t know how I was able to leave Sencha a year ago, but every time I interact with Abe, Don, Jacky, Tommy, Jamie, Rob, Nige, and all of the other rockstars at that place I’m reminded what a great and unique time that was. Really looking forward to what tomorrow brings!

Autotesting JavaScript with Jasmine and Guard

One of the things I really loved about Rails in the early days was that it introduced me to the concept of autotest – a script that would watch your file system for changes and then automatically execute your unit tests as soon as you change any file.

Because the unit test suite typically executes quickly, you’d tend to have your test results back within a second or two of hitting save, allowing you to remain in the editor the entire time and only break out the browser for deeper debugging – usually the command line output and OS notifications (growl at the time) would be enough to set you straight.

This was a fantastic way to work, and I wanted to get there again with JavaScript. Turns out it’s pretty easy to do this. Because I’ve used a lot of ruby I’m most comfortable using its ecosystem to achieve this, and as it happens there’s a great way to do this already.

Enter Guard

Guard is a simple ruby gem that scans your file system for changes and runs the code of your choice whenever a file you care about is saved. It has a great ecosystem around it which makes automating filesystem-based triggers both simple and powerful. Let’s start by making sure we have all the gems we need:

gem install jasmine jasmine-headless-webkit guard-jasmine-headless-webkit guard \
 guard-livereload terminal-notifier-guard --no-rdoc --no-ri

This just installs a few gems that we’re going to use for our tests. First we grab the excellent Jasmine JavaScript BDD test framework via its gem – you can use the framework of your just but I find Jasmine both pleasant to deal with and it generally Just Works. Next we’re going to add the ‘jasmine-headless-webkit’ gem and its guard twin, which use phantomjs to run your tests on the command line, without needing a browser window.

Next up we grab guard-livereload, which enables Guard to act as a livereload server, automatically running your full suite in the browser each time your save a file. This might sound redundant – our tests are already going to be executed in the headless webkit environment, so why bother running them in the browser too? Well, the browser Jasmine runner tends to give a lot more information when something goes wrong – stack traces and most importantly a live debugger.

Finally we add the terminal-notifier-guard gem, which just allows guard to give us a notification each time the tests finish executing. Now we’ve got our dependencies in line it’s time to set up our environment. Thankfully both jasmine and guard provide simple scripts to get started:

jasmine init

guard init

And we’re ready to go! Let’s test out our setup by running `guard`:


What you should see at this point is something like this:


Terminal output after starting guard

We see guard starting up, telling us it’s going to use TerminalNotifier to give us an OS notification every time the tests finish running, and that it’s going to use JasmineHeadlessWebkit to run the tests without a browser. You’ll see that 5 tests were run in about 5ms, and you should have seen an OS notification flash up telling you the same thing. This is great for working on a laptop where you don’t have the screen real estate to keep a terminal window visible at all times.

What about those 5 tests? They’re just examples that were generated by `jasmine init`. You can find them inside the spec/javascripts directory and by default there’s just 1 – PlayerSpec.js.

Now try editing that file and hitting save – nothing happens. The reason for this is that the Guardfile generated by `guard init` isn’t quite compatible out of the box with the Jasmine folder structure. Thankfully this is trivial to fix – we just need to edit the Guardfile.

If you open up the Guardfile in your editor you’ll see it has about 30 lines of configuration. A large amount of the file is comments and optional configs, which you can delete if you like. Guard is expecting your spec files to have the format ‘my_spec.js’ – note the ‘_spec’ at the end.

To get it working the easiest way is to edit the ‘spec_location’ variable (on line 7 – just remove the ‘_spec’), and do the same to the last line of the `guard ‘jasmine-headless-webkit’ do` block. You should end up with something like this:

spec_location = "spec/javascripts/%s"

guard 'jasmine-headless-webkit' do
watch(%r{^public/javascripts/(.*)\.js$}) { |m| newest_js_file(spec_location % m[1]) }
watch(%r{^app/assets/javascripts/(.*)\.(js|coffee)$}) { |m| newest_js_file(spec_location % m[1]) }
watch(%r{^spec/javascripts/(.*)\..*}) { |m| newest_js_file(spec_location % m[1]) }

Once you save your Guardfile, there’s no need to restart guard, it’ll notice the change to the Guardfile and automatically restart itself. Now when you save PlayerSpec.js again you’ll see the terminal immediately run your tests and show your the notification that all is well (assuming your tests still pass!).

So what are those 4 lines inside the `guard ‘jasmine-headless-webkit’ do` block? As you’ve probably guessed they’re just the set of directories that guard should watch. Whenever any of the files matched by the patterns on those 4 lines change, guard will run its jasmine-headless-webkit command, which is what runs your tests. These are just the defaults, so if your JS files are not found inside those folders jus update it to point to the right place.


The final part of the stack that I use is livereload. Livereload consists of two things – a browser plugin (available for Chrome, Firefox and others), and a server, which have actually already set up with Guard. First you’ll need to install the livereload browser plugin, which is extremely simple.

Because the livereload server is already running inside guard, all we need to do is give our browser a place to load the tests from. Unfortunately the only way I’ve found to do this is to open up a second terminal tab and in the same directory run:

rake jasmine

This sets up a lightweight web server that runs on http://localhost:8888. If you go to that page in your browser now you should see something like this:


livereload in the browser – the livereload plugin is immediately to the right of the address bar

Just hit the livereload button in your browser (once you’ve installed the plugin), edit your file again and you’ll see the browser automatically refreshes itself and runs your tests. This step is optional but I find it extremely useful to get a notification telling me my tests have started failing, then be able to immediately tab into the browser environment to get a full stack trace and debugging environment.

That just about wraps up getting autotest up and running. Next time you come back to your code just run `guard` and `rake jasmine` and you’ll get right back to your new autotesting setup. And if you have a way to have guard serve the browser without requiring the second tab window please share in the comments!

On Leaving Sencha

As some of you may know, I left Sencha last week to move to another startup just up the road in San Mateo. Leaving the company was a hugely difficult thing to do for lots of reasons, some obvious, some less so. I’d like to share a few thoughts on my time there and look forward a little to the future.

I first came across Sencha’s products when I saw an early preview of Ext JS 2 way back in 2007. I thought it was amazing stuff, and I started using it all over the place despite being a Ruby guy at the time. As time went by and I got deeper into the language and the framework, it became clear that JavaScript was the future, even though most people at the time still thought that was a little crazy.

I didn’t really intend to join the company. I was having fun writing components and exploring the framework from the outside already, but a chance meeting in San Francisco with the team changed all that. What I found was a small but immensely talented group of people who loved what they did – writing awesome frameworks all day. Underqualified though I felt, being invited into that group was an honor I couldn’t really refuse.

Early Days

When I started back in late 2009, Ext JS 3.1 was just being wrapped up for release so I leapt straight into creating 3.2. Having only ever consumed the framework before, making the leap to creating brand new components was quite a challenge. Thankfully Sencha can count many veterans in its ranks, and Jamie in particular demonstrated his saintly patience in bringing me up to speed.

Ext JS 3.2 saw the addition of animated DataView transitions, composite fields and a few Toolbar plugins. It also required some upgrades to Store, which was a horrifying enough experience that I’d spend a few weeks rewriting the entire data package for Sencha Touch and Ext JS 4. 3.2 also saw the first of my allegedly bombastic blog posts (I’m just enthusiastic…)!

All this time we were a very small group working out of a picturesque little office on University Avenue in Palo Alto. During that first year we grew to maybe 25 people and all fit happily into the one big open plan room, descending en masse upon one of the many restaurants along the strip or bringing food back to eat in the sunny courtyard outside the office.

The original Palo Alto office. My desk was at the lower left

The original Palo Alto office. My desk was at the lower left

I think of that time as the happiest part of my Sencha experience. Somehow I’d found myself in the heart of Silicon Valley surrounded by unbelievably talented people, creating groundbreaking products – some of which we were even allowed to give away for free! We worked like crazy, often well into the early hours of the morning, but it was a lot of fun and I think we created a lot we can be proud of in that time.

Creating Sencha Touch, Learning how to Conference

Not long after Ext JS 3.2 went final, and in parallel with Ext JS 3.3, we started creating Sencha Touch. The initial work was all from Tommy and Dave, before I got a chance to jump in and start writing the new data package. Over time most of the team got a chance to put their name on Touch as we raced to create the world’s first HTML5 mobile app framework. Creating a new product from scratch like that was an awesome experience, and the final product was pretty good (though nowhere near as good as we’d get it with 2.0).

SenchaCon 2010 was scheduled for mid-November and we’d decided we wanted to make a big splash by releasing Sencha Touch – for free. Naturally, this meant a lot of work in a very short period of time in the months running up to the conference. I have vivid memories of a particular evening (read: 3am) in the office just before an imminent release. That can be stressful enough at the best of times but this particular evening our fire alarm would not stop going off. I don’t know whether it was the people, the project or the pressure, but what should have been a dreadful night was a really fun experience. And I think it paid off – we shipped on time at the conference, but only just.

This would be a pattern we’d repeat more than once – working night and day to create both products and presentations that have an immovable deadline. Once more it amazes me how talented my friends at Sencha really are: how many developers do you know who can write great code and deliver world-class conference presentations? That all came from a lot of hard work but it’s one more reason why it was so hard to leave that group of people behind.

This happened a lot in the line of duty

This happened a lot in the line of duty

Later Days

Later on, our time was dominated first by Ext JS 4, then by Sencha Touch 2. I was able to make a couple of contributions to Ext JS 4 – chiefly the new data package plus an evolution of the MVC architecture that debuted in Sencha Touch 1. I probably spent as much time writing documentation as I did writing code though, which is a pattern I’d later repeat on Sencha Touch 2. For whatever reason there’s a misalignment in my brain that makes me pretty passionate about docs, so if you’re reading the guides and class docs from those projects and none of it makes sense, well, sorry! (but you should see how it was before…)

By this time we’d outgrown our little office in Palo Alto and moved to a much bigger space in Redwood City. With 5x the floor space at our disposal the company started growing like crazy, easily expanding by a factor of 10 during the time I was there. That transition was harder than I expected – at 10 people it was like a large family, at 100 it was definitely a Company. I think a lot of that is down to Sencha’s success, but it still caught me off guard having never been through that before.

I think the thing I’m proudest of during my time at Sencha was the release of Sencha Touch 2. This was the first release where we got (almost) everything right – the quality was high, the performance was great, and we finally cracked MVC. We even launched with relatively good docs and examples from day one, though I’ve learned by now that you can never have enough of that stuff.


As well as getting to work with so many talented people inside the company, I’ve also been lucky enough to meet a huge number of people from the Sencha community. If anything you guys seem even more passionate about our stuff than we are. Until SenchaCon I could honestly say I’d never been mobbed but for those few days a year you make us all feel like rockstars. We may not say it at the time but I know everyone involves gets a huge high from those interactions, so thanks.

While I’m at a new company now I expect to stay active in the Sencha community, I’m far too attached to what we created together to leave that behind any time soon. I’ll stay active on the forums and maybe even blog once a while – if you want to get in touch feel free to reach out here, on twitter or linkedin, or if you’re near Palo Alto maybe I’ll buy you a beer.

Sencha’s best days are ahead of it and they have a great team there to deliver on the mission. I remain a big fan of the company, its people, its products and especially its community and can’t wait to see what happens next.

%d bloggers like this: