AboutBlogContact
Backend EngineeringApril 7, 2005 6 min read 85Updated: May 18, 2026

Ajax: The Name That Changed How We Think About the Web (2005)

AunimedaAunimeda
📋 Table of Contents

Ajax: The Name That Changed How We Think About the Web (2005)

On February 18, 2005, Jesse James Garrett at Adaptive Path published an essay titled "Ajax: A New Approach to Web Applications." It was not a technical breakthrough. XMLHttpRequest had been in Internet Explorer since 1999 as an ActiveX component. Mozilla had a native implementation since 2002. The specification was years old.

What Garrett did was give the pattern a name and articulate what it made possible. Before "Ajax," developers who used XMLHttpRequest were doing something unnamed and niche. After "Ajax," it was a recognized architectural approach with a vocabulary everyone could use.

Google Maps launched in February 2005. Gmail had launched in beta in April 2004. Both used XMLHttpRequest to update page content without reloading. After Garrett's essay, every developer in the industry understood why these products felt different - and wanted to build that way.


What the Ajax Pattern Actually Was

Garrett's definition was specific. Ajax was not just XMLHttpRequest. It was a combination:

  1. Standards-based presentation using XHTML + CSS
  2. Dynamic display and interaction using the Document Object Model
  3. Data interchange using XML and XSLT (JSON wasn't the default yet - that came later)
  4. Asynchronous data retrieval using XMLHttpRequest
  5. JavaScript binding everything together

The architectural shift: instead of the server rendering complete HTML pages on every request, the browser became a thin application layer. The server served data. The browser rendered it. The interaction loop was: user action → JavaScript → XMLHttpRequest → server response → DOM update. No page reload.

// The raw Ajax pattern, 2005 - before jQuery abstracted it
// This is what every developer wrote by hand

function ajax(options) {
    var xhr;

    // Cross-browser XHR creation - IE used ActiveX, others had native
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        // IE 5, 6
        try       { xhr = new ActiveXObject('MSXML2.XMLHTTP.6.0'); }
        catch (e) { xhr = new ActiveXObject('Microsoft.XMLHTTP'); }
    }

    if (!xhr) {
        options.error && options.error('XMLHttpRequest not available');
        return;
    }

    xhr.onreadystatechange = function() {
        if (xhr.readyState !== 4) return;
        if (xhr.status === 200) {
            options.success && options.success(xhr.responseText);
        } else {
            options.error && options.error(xhr.status, xhr.statusText);
        }
    };

    xhr.open(options.method || 'GET', options.url, true);  // true = async

    if (options.method === 'POST') {
        xhr.setRequestHeader(
            'Content-Type',
            'application/x-www-form-urlencoded'
        );
        xhr.send(options.data || null);
    } else {
        // IE 6 cache-busting: it cached GET requests aggressively
        var url = options.url;
        if (url.indexOf('?') === -1) {
            url += '?_t=' + new Date().getTime();
        } else {
            url += '&_t=' + new Date().getTime();
        }
        xhr.send(null);
    }
}

// Usage - search with live results
ajax({
    url: '/search.php?q=' + encodeURIComponent(query),
    success: function(html) {
        document.getElementById('search-results').innerHTML = html;
        document.getElementById('loading').style.display = 'none';
    },
    error: function(status) {
        alert('Search failed: ' + status);
    }
});

A Real Ajax Feature: Live Search (2005)

The "live search" was the hello-world of Ajax in 2005. Type in a box - results appear without submitting a form:

// livesearch.js - 2005 implementation
// No debounce library. setTimeout by hand.

var searchTimer = null;

function initLiveSearch() {
    var input = document.getElementById('search-input');
    if (!input) return;

    input.onkeyup = function() {
        // Clear previous timer - debounce at 300ms
        if (searchTimer) clearTimeout(searchTimer);

        var query = input.value;
        if (query.length < 2) {
            document.getElementById('live-results').innerHTML = '';
            return;
        }

        document.getElementById('live-results').innerHTML =
            '<p class="loading">Searching...</p>';

        searchTimer = setTimeout(function() {
            performSearch(query);
        }, 300);
    };
}

function performSearch(query) {
    var xhr;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else {
        xhr = new ActiveXObject('Microsoft.XMLHTTP');
    }

    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            document.getElementById('live-results').innerHTML = xhr.responseText;
        }
    };

    // Server returns an HTML fragment, not a full page
    xhr.open('GET',
        '/search.php?q=' + encodeURIComponent(query) +
        '&ajax=1&_t=' + new Date().getTime(),
        true
    );
    xhr.send(null);
}

window.onload = initLiveSearch;

Server side (PHP returning an HTML fragment):

<?php
// search.php - 2005 server, handles both Ajax and full-page requests

$query   = isset($_GET['q']) ? trim($_GET['q']) : '';
$is_ajax = isset($_GET['ajax']) && $_GET['ajax'] == '1';

if (strlen($query) < 2) {
    if ($is_ajax) exit;
    header('Location: /');
    exit;
}

$q = mysql_real_escape_string($query);
$results = mysql_query(
    "SELECT id, title, excerpt FROM posts
     WHERE MATCH(title, content) AGAINST ('$q' IN BOOLEAN MODE)
       AND published = 1
     LIMIT 10"
);

if ($is_ajax) {
    // Return only the results fragment - not the full HTML page
    if (mysql_num_rows($results) === 0) {
        echo '<p>No results for <em>' . htmlspecialchars($query) . '</em></p>';
        exit;
    }
    echo '<ul class="search-results">';
    while ($row = mysql_fetch_assoc($results)) {
        echo '<li>';
        echo '<a href="/post/' . $row['id'] . '">';
        echo htmlspecialchars($row['title']);
        echo '</a>';
        echo '<p>' . htmlspecialchars($row['excerpt']) . '</p>';
        echo '</li>';
    }
    echo '</ul>';
    exit;
}

// Non-Ajax: render full page
include 'header.php';
// ... full page render
?>

The JSON Question: Why Were We Still Using XML?

In 2005, the "A" in Ajax officially stood for "Asynchronous" and the "X" for "XML." The original pattern used XML as the data format between client and server:

<!-- The XML response that "proper" Ajax was supposed to use -->
<?xml version="1.0" encoding="utf-8"?>
<results>
  <post>
    <id>42</id>
    <title>Getting Started with Ajax</title>
    <excerpt>Ajax changes everything about how web apps work...</excerpt>
  </post>
</results>
// Parsing XML in JavaScript - painful in 2005
var xml = xhr.responseXML;
var posts = xml.getElementsByTagName('post');
for (var i = 0; i < posts.length; i++) {
    var title = posts[i].getElementsByTagName('title')[0].firstChild.nodeValue;
    // ...
}

In practice, most developers returned HTML fragments (as in the search example above) or started using a format Douglas Crockford had been promoting: JSON. JSON parsing in 2005 was eval() - there was no JSON.parse() until 2009 (ES5). But it was dramatically simpler than parsing XML DOM trees.

The shift from XML to JSON as the default Ajax data format happened between 2005 and 2008. By the time jQuery 1.0 shipped in August 2006, its $.getJSON() method made JSON the obvious default.


What 2005 Established

The year Ajax was named established that the browser was an application runtime, not a document viewer. This was not a new technical capability - it had existed since 1999. What changed was the mental model. Once developers understood the pattern and had a name for it, adoption was rapid.

By the end of 2005:

  • Google Suggest was live and widely noticed
  • Google Maps had changed user expectations for web interactivity
  • Ruby on Rails 1.0 shipped with built-in Ajax helpers using prototype.js
  • Every web framework was adding Ajax support
  • Developers were asking "how do I make this not reload the page?" as a standard question

The web would never go back to full-page reload as the default interaction model.


Aunimeda builds production-grade backend systems - APIs, microservices, real-time applications, and system integrations.

Contact us for backend engineering services. See also: Custom Software Development, Web Development

Read Also

Why We Chose Node.js in 2011aunimeda
Backend Engineering

Why We Chose Node.js in 2011

In 2011 Node.js was 2 years old, had no LTS, and most PHP developers thought it was a toy. We moved a real-time dashboard to it anyway. Here's the exact reasoning, the risks we accepted, and what happened.

The Node.js Revolution (2011): How JavaScript Conquered the Serveraunimeda
Backend Engineering

The Node.js Revolution (2011): How JavaScript Conquered the Server

Ryan Dahl showed Node.js at JSConf 2009. By 2011 we were running it in production. Non-blocking I/O, npm, and the realization that one language could run everywhere changed how we hired, how we built, and how we thought.

Node.js: Ryan Dahl's 45-Minute Talk That Rewrote Backend Development (2009)aunimeda
Backend Engineering

Node.js: Ryan Dahl's 45-Minute Talk That Rewrote Backend Development (2009)

On November 8, 2009, Ryan Dahl presented Node.js at JSConf EU in Berlin. He showed JavaScript running on the server with non-blocking I/O. The audience sat in silence, then gave a standing ovation. Within three years, Node.js had more packages than any other programming language ecosystem. This is what he built and why it worked.

Need IT development for your business?

We build websites, mobile apps and AI solutions. Free consultation.

Get Consultation All articles