diff --git a/doc/api/modules.markdown b/doc/api/modules.markdown
index eec27b2d839e..1bb185e17665 100644
--- a/doc/api/modules.markdown
+++ b/doc/api/modules.markdown
@@ -330,6 +330,38 @@ Because `module` provides a `filename` property (normally equivalent to
 `__filename`), the entry point of the current application can be obtained
 by checking `require.main.filename`.
 
+## AMD Compatibility
+
+Node's modules have access to a function named `define`, which may be
+used to specify the module's return value.  This is not necessary in node
+programs, but is present in the node API in order to provide
+compatibility with module loaders that use the Asynchronous Module
+Definition pattern.
+
+The example module above could be structured like so:
+
+    define(function (require, exports, module) {
+      var PI = Math.PI;
+
+      exports.area = function (r) {
+        return PI * r * r;
+      };
+
+      exports.circumference = function (r) {
+        return 2 * PI * r;
+      };
+    });
+
+* Only the last argument to `define()` matters.  Other module loaders
+  sometimes use a `define(id, [deps], cb)` pattern, but since this is
+  not relevant in node programs, the other arguments are ignored.
+* If the `define` callback returns a value other than `undefined`, then
+  that value is assigned to `module.exports`.
+* **Important**: Despite being called "AMD", the node module loader **is
+  in fact synchronous**, and using `define()` does not change this fact.
+  Node executes the callback immediately, so please plan your programs
+  accordingly.
+
 ## Addenda: Package Manager Tips
 
 The semantics of Node's `require()` function were designed to be general
diff --git a/lib/module.js b/lib/module.js
index 308fd4e8e308..06fa80fe9c89 100644
--- a/lib/module.js
+++ b/lib/module.js
@@ -381,6 +381,7 @@ Module.prototype._compile = function(content, filename) {
   require.cache = Module._cache;
 
   var dirname = path.dirname(filename);
+  var define = makeDefine(require, self);
 
   if (Module._contextLoad) {
     if (self.id !== '.') {
@@ -397,6 +398,7 @@ Module.prototype._compile = function(content, filename) {
       sandbox.module = self;
       sandbox.global = sandbox;
       sandbox.root = root;
+      sandbox.define = define;
 
       return runInNewContext(content, sandbox, filename, true);
     }
@@ -408,6 +410,7 @@ Module.prototype._compile = function(content, filename) {
     global.__filename = filename;
     global.__dirname = dirname;
     global.module = self;
+    global.define = define;
 
     return runInThisContext(content, filename, true);
   }
@@ -419,10 +422,44 @@ Module.prototype._compile = function(content, filename) {
   if (filename === process.argv[1] && global.v8debug) {
     global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0);
   }
-  var args = [self.exports, require, self, filename, dirname];
+
+  var args = [self.exports, require, self, filename, dirname, define];
   return compiledWrapper.apply(self.exports, args);
 };
 
+// AMD compatibility
+function makeDefine(require, module) {
+  var called = false;
+  function define() {
+    if (called) {
+      throw new Error("define() may only be called once.");
+    }
+    called = true;
+
+    // only care about the last argument
+    var cb = arguments[ arguments.length - 1 ];
+
+    // set exports immediately:
+    // define({ foo: "bar" })
+    if (typeof cb !== 'function') {
+      module.exports = cb;
+      return;
+    }
+
+    var ret = cb(require, module.exports, module);
+
+    if (ret !== undefined) {
+      // set exports with return statement
+      // define(function () { return { foo: "bar" } })
+      module.exports = ret;
+    }
+  }
+
+  return define;
+}
+
+
+
 // Native extension for .js
 Module._extensions['.js'] = function(module, filename) {
   var content = NativeModule.require('fs').readFileSync(filename, 'utf8');
diff --git a/src/node.cc b/src/node.cc
index 4f01727fcd19..65dcf676ad8d 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1287,7 +1287,7 @@ void DisplayExceptionLine (TryCatch &try_catch) {
     //
     // When reporting errors on the first line of a script, this wrapper
     // function is leaked to the user. This HACK is to remove it. The length
-    // of the wrapper is 62. That wrapper is defined in src/node.js
+    // of the wrapper is 70. That wrapper is defined in src/node.js
     //
     // If that wrapper is ever changed, then this number also has to be
     // updated. Or - someone could clean this up so that the two peices
@@ -1295,7 +1295,7 @@ void DisplayExceptionLine (TryCatch &try_catch) {
     //
     // Even better would be to get support into V8 for wrappers that
     // shouldn't be reported to users.
-    int offset = linenum == 1 ? 62 : 0;
+    int offset = linenum == 1 ? 70 : 0;
 
     fprintf(stderr, "%s\n", sourceline_string + offset);
     // Print wavy underline (GetUnderline is deprecated).
diff --git a/src/node.js b/src/node.js
index 1f512a5f6f17..581bb94b8438 100644
--- a/src/node.js
+++ b/src/node.js
@@ -436,7 +436,7 @@
   };
 
   NativeModule.wrapper = [
-    '(function (exports, require, module, __filename, __dirname) { ',
+    '(function (exports, require, module, __filename, __dirname, define) { ',
     '\n});'
   ];
 
diff --git a/test/fixtures/amd-modules/extra-args.js b/test/fixtures/amd-modules/extra-args.js
new file mode 100644
index 000000000000..a81d48c3b246
--- /dev/null
+++ b/test/fixtures/amd-modules/extra-args.js
@@ -0,0 +1,3 @@
+define(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, function(r, e, m) {
+  exports.ok = require("./regular.js").ok;
+});
diff --git a/test/fixtures/amd-modules/module-exports.js b/test/fixtures/amd-modules/module-exports.js
new file mode 100644
index 000000000000..496440eedf76
--- /dev/null
+++ b/test/fixtures/amd-modules/module-exports.js
@@ -0,0 +1,3 @@
+define(function(require, exports, module) {
+  module.exports = { ok: require("./regular.js").ok };
+});
diff --git a/test/fixtures/amd-modules/object.js b/test/fixtures/amd-modules/object.js
new file mode 100644
index 000000000000..93b840b61bfb
--- /dev/null
+++ b/test/fixtures/amd-modules/object.js
@@ -0,0 +1 @@
+define({ ok: require("./regular.js").ok });
diff --git a/test/fixtures/amd-modules/regular.js b/test/fixtures/amd-modules/regular.js
new file mode 100644
index 000000000000..013a6cfd4339
--- /dev/null
+++ b/test/fixtures/amd-modules/regular.js
@@ -0,0 +1,14 @@
+var R = require;
+var E = exports;
+var M = module;
+
+define(function(require, exports, module, nothingHere) {
+  if (R !== require) throw new Error("invalid require in AMD cb");
+  if (E !== exports) throw new Error("invalid exports in AMD cb");
+  if (M !== module) throw new Error("invalid module in AMD cb");
+  if (nothingHere !== undefined) {
+    throw new Error("unknown args to AMD cb");
+  }
+
+  exports.ok = { ok: true };
+});
diff --git a/test/fixtures/amd-modules/return.js b/test/fixtures/amd-modules/return.js
new file mode 100644
index 000000000000..6ad01321c2e5
--- /dev/null
+++ b/test/fixtures/amd-modules/return.js
@@ -0,0 +1,3 @@
+define(function() {
+  return { ok: require("./regular.js").ok };
+});
diff --git a/test/simple/test-module-loading.js b/test/simple/test-module-loading.js
index 5f648f0c784b..421fcbf84461 100644
--- a/test/simple/test-module-loading.js
+++ b/test/simple/test-module-loading.js
@@ -187,6 +187,26 @@ try {
 assert.equal(require(loadOrder + 'file8').file8, 'file8/index.reg', msg);
 assert.equal(require(loadOrder + 'file9').file9, 'file9/index.reg2', msg);
 
+
+// test the async module definition pattern modules
+var amdFolder = '../fixtures/amd-modules';
+var amdreg = require(amdFolder + '/regular.js');
+assert.deepEqual(amdreg.ok, {ok: true}, 'regular amd module failed');
+
+// make sure they all get the same 'ok' object.
+var amdModuleExports = require(amdFolder + '/module-exports.js');
+assert.equal(amdModuleExports.ok, amdreg.ok, 'amd module.exports failed');
+
+var amdReturn = require(amdFolder + '/return.js');
+assert.equal(amdReturn.ok, amdreg.ok, 'amd return failed');
+
+var amdObj = require(amdFolder + '/object.js');
+assert.equal(amdObj.ok, amdreg.ok, 'amd object literal failed');
+
+var amdExtraArgs = require(amdFolder + '/extra-args.js');
+assert.equal(amdExtraArgs.ok, amdreg.ok, 'amd extra args failed');
+
+
 process.addListener('exit', function() {
   assert.ok(common.indirectInstanceOf(a.A, Function));
   assert.equal('A done', a.A());