An experiment with Bind (on github). For each lookup, bind makes a HTTP GET on a webserver which answers a bit of json. With this backend, you are free in your choice of database. You don’t have to change bind code, just write a little webserver.

require 'sinatra'

db = {
  "www" => "192.168.0.105",
  "ns1" => "192.168.0.55",
  "ns2" => "192.168.0.54"
}

get '/example.com/lookup' do
  content_type "application/json"

  name = params["name"]

  return '{"type" : "NS", "field" : "ns1.example.com."}' if name == "@"
  return '{}' unless db.has_key?(name)

  '{"type" : "A", "field" : "#{db[name]}"}'
end

get '/example.com/authority' do
  content_type "application/json"

  '{
      "data" : [
          {
              "type" : "SOA",
              "field" : [
                  "ns1.example.com.",
                  "dns.example.com.",
                  2010122701
              ]
          },
          {
              "type" : "NS",
              "field" : "ns1.example.com."
          },
          {
              "type" : "NS",
              "field" : "ns2.example.com."
          }
      ]
  }'
end

and in named.conf,

controls { /* empty */ };

options {
  directory "/var/cache/bind";

  allow-transfer { any; };
  // auth-nxdomain no;
  listen-on-v6 { any; };
};

zone "example.com" {
  type master;
  database "remote http://127.0.0.1:4567";
};

Easy? When I do

$ nslookup www.example.com

Bind asks my webserver

GET /[zone name]/lookup?name=[subdomain]

Sinatra answers

{"type" : "A", "field" : "192.168.0.105"}