Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Adrian Cole edited this page · 6 revisions


Denominator supports geo (directional) record sets. Unlike normal case, where there's only a single record set per name and type, geo record sets must also differentiate by qualifier (ResourceRecordSet.qualifier()). This qualifier is a friendly name for a map of territories (Geo.territories()) which can view the set, such as Japan. In practice, only one geo record set is visible to a resolver. Which is chosen corresponds to the well-known location of the subnet of the ISP in use. As such, you can think of geo record sets as server-side profiles, which contain the policies used to serve up names conditionally based on client information.

For example, consider the following tuples: [ CNAME US], [ CNAME EU], [ CNAME Others]. If I'm requesting the name of from Comcast in San Francisco, it is very likely I'll receive the data from the US group.


This design of our geo support came via issue #90 and discussions such as google group. Read-only support was added in issue #121.

Supported Record Types

Types supported for geo configs are typically a subset of normal records. Provider.profileToRecordTypes() for key geo indicates what is supported, and checking this value allows you to safeguard code.

Geo Profile

ResourceRecordSet.qualifier() indicates the group name chosen by the user. ex. US-East

Geo is a profile which indicates directional dns support. This type contains the following field:

  • regions: subset of regions defined by the system. ex. "South America" :["Colombia", "Ecuador"... in ultradns


optionally exposed if the provider supports it. Similar to ResourceRecordSetApi, except that name and type are ambiguous. For example, there could be a separate rrset for the CNAME for US-East and US-West profiles.


There are many differences between ultradns and dynect region codes. This will help validate changes that would otherwise result in errors, such as mis-spelling Alabama as alabama

Common commands

Change TTL for a group of regions

When readying for a change in territories, lowering the TTL will give most clients the chance to pick up changes faster, at the expense of more DNS hits on the servers. Typically, this command is used for a planned change, and is reverted back once the change completes.

ex. the following will apply the ttl 600 if not already set:

ResourceRecordSet<?> rrset = geoApi.getByNameTypeAndQualifier("", "CNAME", "Europe").get();

Change a region group

Region mapping changes can be useful for AB testing, cautiously rolling out new versions of software, dealing with jurisdictionally sensitive apps, and multi-region issues such as failover. Regions in denominator are represented by a Multimap where the key is the coarse grained territories and the values are sub-territories. For example, in UltraDNS, the region United States (US) contains a list of states (ex. Utah) and territories such as Armed Forces Americas. The applyRegionsToNameTypeAndGroup command allows you to update the region mappings corresponding to a geo group.

ex. the following will remove Utah from the regions

import static;
import static;
import static
import static denominator.model.profile.Geo.asGeo;
ResourceRecordSet<?> rrset = geoApi.getByNameTypeAndQualifier("", "CNAME", "US-West").get();

Multimap<String, String> update = filterValues(asGeo.apply(existing).regions(), not(equalTo("Utah")));



There are significantly more web service operations required to aggregate all record sets on most providers. Typically, there's an operation to list normal record sets, and then a series of operations to query specialized pools used for geo-config. The AllProfileResourceRecordSetApi is introduced for a couple reasons. One is that we don't want to complicate portability and coding of "normal" denominator providers by renaming ResourceRecordSetApi to BasicResourceRecordSetApi. Further, since profiles can allow for duplication on the query [name, type], we cannot support the method ResourceRecordSetApi.getByNameAndType safely, and instead have to allow it to expose duplicates via AllProfileResourceRecordSetApi.listByNameAndType. For example, the site of type CNAME could be ambigious, if it had a profile for multiple regions, such as US-West and EU-West. Since profiles make life a little more difficult, and this complexity isn't valid for "normal" records, we left ResourceRecordSetApi alone, and added an similarly named class to expose "all" stuff.


The command-line has been extended to add operations for the group geo.

$ denominator -p mock geo -z types
$ denominator -p mock geo -z regions
Anonymous Proxy (A1)        : Anonymous Proxy
Satellite Provider (A2)     : Satellite Provider
Unknown / Uncategorized IPs : Unknown / Uncategorized IPs
United States (US)          : Alabama;Alaska;Arizona;Arkansas;Armed Forces Americas;Armed Forces Europe, Middle East, and Canada;Armed Forces Pacific;California;Colorado;Connecticut;Delaware;District of Columbia;Florida;Georgia;Hawaii;Idaho;Illinois;Indiana;Iowa;Kansas;Kentucky;Louisiana;Maine;Maryland;Massachusetts;Michigan;Minnesota;Mississippi;Missouri;Montana;Nebraska;Nevada;New Hampshire;New Jersey;New Mexico;New York;North Carolina;North Dakota;Ohio;Oklahoma;Oregon;Pennsylvania;Rhode Island;South Carolina;South Dakota;Tennessee;Texas;Undefined United States;United States Minor Outlying Islands;Utah;Vermont;Virginia;Washington;West Virginia;Wisconsin;Wyoming
$ denominator -p mock geo -z list                           CNAME  0 antarctica {Antarctica=[Bouvet Island, French Southern Territories, Antarctica]}                           CNAME  300 alazona {United States (US)=[Alaska, Arizona]}                           CNAME  86400 columbador {South America=[Colombia, Ecuador]}                          A      300 alazona {United States (US)=[Alaska, Arizona]}


In order to run tests, you'll need to pass an additional parameter describing the zone which is ok to affect to ./gradlew clean test install

Ex. to affect the zone


  • noResponse: queries for this record will not be answered within the regions applied
  • unconfiguredRegions: we just enumerate the territories as opposed to making a special group, so far.
  • region -> territory value portability. There are many differences between ultradns and dynect region codes. The effort to make them portable is out of scope for this pull request.

Region -> Territory value portability

The below data showcases differences in how regions are mapped in two providers denominator supports. As discussed on the google group, we've tabled attempts to make this information portable. However, this issue can be picked up later.

    "dynect": {
        "11": ["AG", "AI", "AN", "AW", "BB", "BL", "BM", "BS", "BZ", "CA", "CR", "CU", "DM", "DO", "GD", "GL", "GP", "GT", "HN", "HT", "JM", "KN", "KY", "LC", "MF", "MQ", "MS", "MX", "NI", "PA", "PM", "PR", "SV", "TC", "TT", "US", "VC", "VG", "VI"],
        "United States": ["al", "ak", "as", "az", "ar", "aa", "ae", "ap", "ca", "co", "ct", "de", "dc", "fm", "fl", "ga", "gu", "hi", "id", "il", "in", "ia", "ks", "ky", "la", "me", "mh", "md", "ma", "mi", "mn", "ms", "mo", "mt", "ne", "nv", "nh", "nj", "nm", "ny", "nc", "nd", "mp", "oh", "ok", "or", "pw", "pa", "pr", "ri", "sc", "sd", "tn", "tx", "ut", "vt", "vi", "va", "wa", "wv", "wi", "wy"],
        "Canada": ["ab", "bc", "mb", "nb", "nl", "nt", "ns", "nu", "on", "pe", "qc", "sk", "yt"],
        "12": ["AR", "BO", "BR", "CL", "CO", "EC", "FK", "GF", "GY", "PE", "PY", "SR", "UY", "VE"],
        "13": ["AD", "AL", "AT", "AX", "BA", "BE", "BG", "BY", "CH", "CZ", "DE", "DK", "EE", "ES", "EU", "FI", "FO", "FR", "FX", "GB", "GG", "GI", "GR", "HR", "HU", "IE", "IM", "IS", "IT", "JE", "LI", "LT", "LU", "LV", "MC", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT", "RO", "RS", "RU", "SE", "SI", "SJ", "SK", "SM", "TR", "UA", "VA"],
        "14": ["AO", "BF", "BI", "BJ", "BW", "CD", "CF", "CG", "CI", "CM", "CV", "DJ", "DZ", "EG", "EH", "ER", "ET", "GA", "GH", "GM", "GN", "GQ", "GW", "KE", "KM", "LR", "LS", "LY", "MA", "MG", "ML", "MR", "MU", "MW", "MZ", "NA", "NE", "NG", "RE", "RW", "SC", "SD", "SH", "SL", "SN", "SO", "ST", "SZ", "TD", "TG", "TN", "TZ", "UG", "YT", "ZA", "ZM", "ZW"],
        "15": ["AE", "AF", "AM", "AP", "AZ", "BD", "BH", "BN", "BT", "CC", "CN", "CX", "CY", "GE", "HK", "ID", "IL", "IN", "IO", "IQ", "IR", "JO", "JP", "KG", "KH", "KP", "KR", "KW", "KZ", "LA", "LB", "LK", "MM", "MN", "MO", "MV", "MY", "NP", "OM", "PH", "PK", "PS", "QA", "SA", "SG", "SY", "TH", "TJ", "TL", "TM", "TW", "UZ", "VN", "YE"],
        "16": ["AS", "AU", "CK", "FJ", "FM", "GU", "KI", "MH", "MP", "NC", "NF", "NR", "NU", "NZ", "PF", "PG", "PN", "PW", "SB", "TK", "TO", "TV", "UM", "VU", "WF", "WS"],
        "17": ["AQ", "BV", "GS", "HM", "TF"],
        "Fallback": ["@@"],
        "Anonymous Proxy": ["A1"],
        "Other Country": ["O1"],
        "Satellite Provider": ["A2"]
    "ultradns": {
        "Anonymous Proxy (A1)": ["Anonymous Proxy"],
        "Satellite Provider (A2)": ["Satellite Provider"],
        "Unknown / Uncategorized IPs": ["Unknown / Uncategorized IPs"],
        "United States (US)": ["Alabama", "Alaska", "Arizona", "Arkansas", "Armed Forces Americas", "Armed Forces Europe, Middle East, and Canada", "Armed Forces Pacific", "California", "Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Undefined United States", "United States Minor Outlying Islands", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"],
        "Mexico": ["Mexico"],
        "Canada (CA)": ["Alberta", "British Columbia", "Greenland", "Manitoba", "New Brunswick", "Newfoundland and Labrador", "Northwest Territories", "Nova Scotia", "Nunavut", "Ontario", "Prince Edward Island", "Quebec", "Saint Pierre and Miquelon", "Saskatchewan", "Undefined Canada", "Yukon"],
        "The Caribbean": ["Anguilla", "Antigua and Barbuda", "Aruba", "Bahamas", "Barbados", "Bermuda", "British Virgin Islands", "Cayman Islands", "Cuba", "Dominica", "Dominican Republic", "Grenada", "Guadeloupe", "Haiti", "Jamaica", "Martinique", "Montserrat", "Netherlands Antilles", "Puerto Rico", "Saint Barthelemy", "Saint Martin", "Saint Vincent and the Grenadines", "St. Kitts and Nevis", "St. Lucia", "Trinidad and Tobago", "Turks and Caicos Islands", "U.S. Virgin Islands"],
        "Central America": ["Belize", "Costa Rica", "El Salvador", "Guatemala", "Honduras", "Nicaragua", "Panama", "Undefined Central America"],
        "South America": ["Argentina", "Bolivia", "Brazil", "Chile", "Colombia", "Ecuador", "Falkland Islands", "French Guiana", "Guyana", "Paraguay", "Peru", "South Georgia and the South Sandwich Islands", "Suriname", "Undefined South America", "Uruguay", "Venezuela, Bolivarian Republic of"],
        "Europe": ["Aland Islands", "Albania", "Andorra", "Armenia", "Austria", "Azerbaijan", "Belarus", "Belgium", "Bosnia-Herzegovina", "Bulgaria", "Croatia", "Czech Republic", "Denmark", "Estonia", "Faroe Islands", "Finland", "France", "Georgia", "Germany", "Gibraltar", "Greece", "Guernsey", "Hungary", "Iceland", "Ireland", "Isle of Man", "Italy", "Jersey", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Macedonia, the former Yugoslav Republic of", "Malta", "Moldova, Republic of", "Monaco", "Montenegro", "Netherlands", "Norway", "Poland", "Portugal", "Romania", "San Marino", "Serbia", "Slovakia", "Slovenia", "Spain", "Svalbard and Jan Mayen", "Sweden", "Switzerland", "Ukraine", "Undefined Europe", "United Kingdom - England, Northern Ireland, Scotland, Wales", "Vatican City"],
        "Russian Federation": ["Russian Federation"],
        "Middle East": ["Afghanistan", "Bahrain", "Cyprus", "Iran", "Iraq", "Israel", "Jordan", "Kuwait", "Lebanon", "Oman", "Palestinian Territory, Occupied", "Qatar", "Saudi Arabia", "Syrian Arab Republic", "Turkey, Republic of", "Undefined Middle East", "United Arab Emirates", "Yemen"],
        "Africa": ["Algeria", "Angola", "Benin", "Botswana", "Burkina Faso", "Burundi", "Cameroon", "Cape Verde", "Central African Republic", "Chad", "Comoros", "Congo", "Cote d\u0027Ivoire", "Democratic Republic of the Congo", "Djibouti", "Egypt", "Equatorial Guinea", "Eritrea", "Ethiopia", "Gabon", "Gambia", "Ghana", "Guinea", "Guinea-Bissau", "Kenya", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Madagascar", "Malawi", "Mali", "Mauritania", "Mauritius", "Mayotte", "Morocco", "Mozambique", "Namibia", "Niger", "Nigeria", "Reunion", "Rwanda", "Sao Tome and Principe", "Senegal", "Seychelles", "Sierra Leone", "Somalia", "South Africa", "St. Helena", "Sudan", "Swaziland", "Tanzania, United Republic of", "Togo", "Tunisia", "Uganda", "Undefined Africa", "Western Sahara", "Zambia", "Zimbabwe"],
        "Asia": ["Bangladesh", "Bhutan", "British Indian Ocean Territory - Chagos Islands", "Brunei Darussalam", "Cambodia", "China", "Hong Kong", "India", "Indonesia", "Japan", "Kazakhstan", "Korea, Democratic People\u0027s Republic of", "Korea, Republic of", "Kyrgyzstan", "Lao People\u0027s Democratic Republic", "Macao", "Malaysia", "Maldives", "Mongolia", "Myanmar", "Nepal", "Pakistan", "Philippines", "Singapore", "Sri Lanka", "Taiwan", "Tajikistan", "Thailand", "Timor-Leste, Democratic Republic of", "Turkmenistan", "Undefined Asia", "Uzbekistan", "Vietnam"],
        "Australia / Oceania": ["American Samoa", "Australia", "Christmas Island", "Cocos (Keeling) Islands", "Cook Islands", "Fiji", "French Polynesia", "Guam", "Heard Island and McDonald Islands", "Kiribati", "Marshall Islands", "Micronesia , Federated States of", "Nauru", "New Caledonia", "New Zealand", "Niue", "Norfolk Island", "Northern Mariana Islands, Commonwealth of", "Palau", "Papua New Guinea", "Pitcairn", "Samoa", "Solomon Islands", "Tokelau", "Tonga", "Tuvalu", "Undefined Australia / Oceania", "Vanuatu", "Wallis and Futuna"],
        "Antarctica": ["Antarctica", "Bouvet Island", "French Southern Territories"]
Something went wrong with that request. Please try again.