You're viewing the readable version of this site. The interactive extras (search, diagrams, read-aloud) need JavaScript and a current browser. Enable JavaScript; if it is already enabled, update your browser.

Notes · Archive

evergreen

memcache.js for Google App Engine application front-ends?

Caching AJAX responses on the client by mapping App Engine’s datastore to JS objects.

· · 4 min read

javascript, google-app-engine, caching, archive

Cite this
APA
Mangalapilly, Y. J. (2009, July). memcache.js for Google App Engine application front-ends?. Saṃhitā Notes. https://yesudeep.com/blog/memcache-js-for-app-engine/
BibTeX
@online{mangalapilly2009memcache,
  author  = {Yesudeep Jose Mangalapilly},
  title   = {memcache.js for Google App Engine application front-ends?},
  journal = {Sa\d{m}hit\=a Notes},
  year    = {2009},
  month   = {July},
  url     = {https://yesudeep.com/blog/memcache-js-for-app-engine/},
  urldate = {2026-07-09},
}
Plain
Yesudeep Jose Mangalapilly. “memcache.js for Google App Engine application front-ends?.” Saṃhitā Notes, 2009. https://yesudeep.com/blog/memcache-js-for-app-engine/.
RIS
TY  - ELEC
AU  - Mangalapilly, Yesudeep Jose
TI  - memcache.js for Google App Engine application front-ends?
T2  - Saṃhitā Notes
PY  - 2009
UR  - https://yesudeep.com/blog/memcache-js-for-app-engine/
Y2  - 2026-07-09
ER  - 

Note

Originally published on my old WordPress blog in 2009. Preserved here with its original date; the original is still online. A 2026 note for the record: everything here is a period piece — google.appengine.ext.db and jQuery's .live() (removed in jQuery 1.9, 2013) are long gone, and browsers grew localStorage, the Cache API, and proper Cache-Control handling on fetch, which solve this without a hand-rolled cache. Two things were shaky even in 2009: if cached_value: mis-handles empty results (falsy, so they never cache — is not None was the idiom), and encoded datastore keys were never guaranteed to start with a letter; they just happened to. Refreshed in July 2026 with captions and a diagram of the cache path.

Memcached is an in-memory key-value store for small chunks of arbitrary data. It was built to speed up dynamic web applications by alleviating database load. — Brad Fitzpatrick, Memcached Announcement (2003)

  • How early JS applications attempted in-memory response caching before native browser storage APIs existed.
  • The interaction between server-side Memcached and client-side RPC caching.
  • Why hand-rolled client caching required careful invalidation handling for falsy empty result sets.

The Google App Engine datastore is a pretty neat example of a key-value datastore.  Mapping this to JavaScript objects can be fairly straightforward, especially when you need to cache AJAX responses.

The cache shape is still recognizable. A client-side hit avoids the network; on a miss the request falls through to the remote API and datastore. The hand-rolled object was the historical part, not the cache-as-a-layer idea.

An App Engine Model

Let's say you have a Person model defined in your GAE application:

# models.py
from google.appengine.ext import db
from google.appengine.api import memcache

class Person(db.Model):
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    birthdate = db.DateTimeProperty()

    @classmethod
    def get_all(cls):
        cache_key = 'Person.get_all'
        cached_value = memcache.get(cache_key)
        if cached_value:
            return cached_value
        else:
            people = Person.all().fetch(20)
            memcache.set(cache_key, people, 120)  # cache for 2 minutes/120 seconds
            return people

The server-side model cached through App Engine memcache. get_all() stores a datastore result for two minutes.

Getting a list of 20 people (more specifically, Person objects) from the datastore is as easy as calling:

people = Person.get_all()

The cached model read. Callers still ask the model; the cache stays behind the method.

The Person.get_all() method uses memcache to temporarily cache a copy of the data in distributed memory to avoid hitting the datastore every time it is called.  Of course, as you can see, the data is only cached for a particular duration in memory and then cleared away.

What if you could use memcache on the client side to cache server responses?

You can't really use the actual memcached daemon for this purpose, but you can surely emulate memcache behavior using a simple JavaScript object to cache values just like memcached would.  Quite naturally, since the code would be restricted to a single script runtime environment, you wouldn't have distributed memcache either.  But, hey, something is better than nothing.

Caching server responses that result from AJAX calls can make people perceive that your application is pretty quick.  All you're doing to achieve this is avoiding hitting the Web server repeatedly for the same information.  Let's look at a code excerpt:

function get_person(key){
  var person = memcache.get(key);
  if (person){
    return person;
  } else {
    remote_api.get_person(key, function(person){
      memcache.set(key, person, 120000);  // Cache for 2 minutes (120 seconds).
    });
  }
}

A client-side cache check before the remote call. A hit returns without touching the server.

Note that get_person(key) will not send a request to the server if the data is already available in the memcache store.  In the above case, the data is only cached for 2 minutes, after which any call to get_person() will send a request to the server.

Where's the code?

/**
 * memcache.js - A simple memcache-like object implemented in JavaScript.
 * Copyright (c) 2009, happychickoo.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer
 *     in the documentation and/or other materials provided with the
 *     distribution.
 *   * Neither the name of happychickoo nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
this.memcache = {
  datastore: {},
  get: function(key){
    return this.datastore[key];
  },
  set: function(key, value, timeout /* milliseconds */){
    var store = this.datastore;
    if (typeof timeout === 'undefined'){
      timeout = 0;
    }
    store[key] = value;
    if (timeout){
      setTimeout(function(){
        delete store[key];
      }, timeout);
    }
  },
  remove: function(key){
    delete this.datastore[key];
  },
  clear: function(){
    this.datastore = {};
  }
};

The tiny browser-side memcache. Values live in an object and optional timers delete them.

There you go.

How does this help with GAE applications?

App Engine doesn't use a conventional RDBMS to store data.  GAE uses a distributed key-value data store, where every object stored in the database is assigned a unique key that looks something like this:

agttaWxzLXNlY3VyZXIKCxIEVXNlchgdDA

This key is guaranteed to start with an alphabet, which implies you can use it as an identifier for a DOM element. Attaching behaviors to such DOM elements that fetch corresponding data then becomes as easy as doing this (example uses jQuery):

jQuery('ul#people > li').click(function(e){
  var key = jQuery(this).attr('id');
  get_person(key, function(person){
    show_information(person);
  });
});

A DOM-keyed lookup. The list item id becomes the cache key for the person record.

Hope that helps clear out some air.  It should be noted that if you're adding li elements dynamically to the ul#people unordered list, the above event handler will not be called for them.  Instead of using jQuery(...).click(handler), you should consider using jQuery(...).live('click', handler).

Lessons

  • Client-side in-memory caches eliminate network round-trips for repeated reads of immutable or clean data.
  • Check cache existence explicitly with val != undefined=; falsy checks like if (cached_val) cause zero, empty string, or false payloads to register as false cache misses.
  • Using opaque backend entity keys as valid DOM element IDs simplifies client-to-server data binding across asynchronous UI components.

Practice

References

  1. Brad Fitzpatrick. “Distributed Caching with Memcached.” Linux Journal, 2004. — the original design paper for distributed key-value memory caching
  2. Google. “Google App Engine Python Datastore Guide.” Google Developers, 2008. — the entity key structure and query model of Bigtable-backed GAE
  3. W3C. “Service Workers & Cache API Specification.” W3C Recommendation, 2026. — modern browser-native caching that replaced client-side JS object stores

How to cite

APA
Mangalapilly, Y. J. (2009, July). memcache.js for Google App Engine application front-ends?. Saṃhitā Notes. https://yesudeep.com/blog/memcache-js-for-app-engine/
BibTeX
@online{mangalapilly2009memcache,
  author  = {Yesudeep Jose Mangalapilly},
  title   = {memcache.js for Google App Engine application front-ends?},
  journal = {Sa\d{m}hit\=a Notes},
  year    = {2009},
  month   = {July},
  url     = {https://yesudeep.com/blog/memcache-js-for-app-engine/},
  urldate = {2026-07-09},
}
Plain
Yesudeep Jose Mangalapilly. “memcache.js for Google App Engine application front-ends?.” Saṃhitā Notes, 2009. https://yesudeep.com/blog/memcache-js-for-app-engine/.
RIS
TY  - ELEC
AU  - Mangalapilly, Yesudeep Jose
TI  - memcache.js for Google App Engine application front-ends?
T2  - Saṃhitā Notes
PY  - 2009
UR  - https://yesudeep.com/blog/memcache-js-for-app-engine/
Y2  - 2026-07-09
ER  - 

Annotations

Thank you — your note is held for review and will appear once approved.

Thank you — your note is published.

Please sign in below to leave a note.