When we introduced TTLs, we emphasized that your choice of a TTL dictates how current you keep copies of your data at the cost of increased load on your name servers. A low TTL means that name servers outside your network have to get data from your name servers often and therefore keep current. However, your name servers are then peppered by their queries.
You don't have to choose a TTL once and for all, though. You can -- and experienced administrators do -- change TTLs periodically to suit your needs.
Suppose we know that one of our hosts is about to be moved to another network. This host houses the movie.edu film library, a large collection of files our site makes available to Internet users. During normal operation, outside name servers cache the address of our host according to the default TTL set in the $TTL control statement, or for pre-BIND 8.2 name servers, in the SOA record. We set the default TTL for movie.eduto three hours in our sample files. A name server caching the old address record just before the change could have the wrong address for as long as three hours. A loss of connectivity for three hours is unacceptable, though. What can we do to minimize the loss of connectivity? We can lower the TTL so that outside servers cache the address record for a shorter period. By reducing the TTL, we force the outside servers to update their data more frequently, which means that any changes we make when we actually move the system are propagated to the outside world quickly. How long can we make the TTL? Unfortunately, we can't safely use a TTL of zero, which should mean "don't cache this record at all." Some older BIND 4 name servers can't return records with a TTL of zero, instead returning null answers or SERVFAIL errors. Small TTLs, like 30 seconds, are okay, though. The easiest change is to lower the TTL in the $TTL control statement in the db.movie.edu file. If you don't place an explicit TTL on resource records in the zone data files, the name server applies this default TTL to each resource record. If you lower the default TTL, though, the new, lower default applies to all zone data, not just the address of the host being moved. The drawback to this approach is that your name server will be answering a lot more queries since the querying servers will cache all the data in your zone for a shorter period. A better alternative is to put a different TTL only on the affected address record.
To add an explicit TTL on an individual resource record, place it before the IN in the class field. The TTL value is in seconds by default, but you can also specify units of m (minutes), h (hours), d (days), and w (weeks), just as you could in the $TTL control statement. Here's an example of an explicit TTL from db.movie.edu:
If you're observant and have read RFC 1034, you may have noticed a potential problem when loading this record on an older name server: the explicit TTL on cujo's address is one hour, but the TTL field in the SOA record -- ostensibly the minimum TTL for the zone on pre-BIND 8.2 name servers -- is higher. Which takes precedence?cujo 1h IN A 192.253.253.5 ; explicit TTL of 1 hour
If older BINDs followed the original DNS RFCs to the letter, the TTL field in the SOA record would really define the minimum TTL for all resource records in the zone. Thus, you could specify only explicit TTLs larger than this minimum. Older BIND name servers don't work this way, though. In other words, in BIND, "minimum" is not really minimum. Instead, BIND interprets the minimum TTL field in the SOA record as a "default" TTL. (Newer BINDs, of course, have the explicit default TTL set with $TTL to go by.) If there is no TTL on a record, the minimum applies. If there is a TTL on the resource record, BIND allows it even if it is smaller than the minimum. That one record is sent out in responses with the smaller TTL, while all other records are sent out with the "minimum" TTL from the SOA record.
You should also know that when giving out answers, a slave supplies the same TTL a primary master does -- that is, if a primary gives out a TTL of one hour for a particular record, a slave will, too. The slave doesn't decrement the TTL according to how long it's been since it loaded the zone. So, if the TTL of a single resource record is set smaller than the default, both the primary and slave name servers give out the resource record with the same, smaller TTL. If the slave name server has reached the expiration time for the zone, it expires the whole zone. It will never expire an individual resource record within a zone.
So BIND does allow you to put a small TTL on an individual resource record if you know that the data is going to change shortly. Thus, any name server caching that data caches it only for a brief time. Unfortunately, while BIND makes tagging records with a small TTL possible, most administrators don't spend the time to do it. When a host's address changes, you often lose connectivity to it for a while.
More often than not, the host having its address changed is not one of the main hubs on the site, so the outage affects few people. If one of the mail hubs or a major web server or FTParchive -- like the film library -- is moving, though, a day's loss of connectivity may be unacceptable. In cases like this, the administrator should plan ahead and reduce the TTL on the data to be changed.
Remember that the TTL on the affected data needs to be lowered before the change takes place. Reducing the TTL on a workstation's address record and changing the workstation's address simultaneously may do you little or no good; the address record may have been cached seconds before you made the change and linger until the old TTL times out. And be sure to factor in the time it'll take your slaves to load from your primary master. For example, if your default TTL is 12 hours and your refresh interval is 3 hours, be sure to lower the TTLs at least 15 hours ahead of time, so that by the time you move the host, all the old, longer-TTL records will have timed out. Of course, if all your slaves are BIND 8 or 9 name servers that use NOTIFY, the slaves shouldn't take the full refresh interval to synch up.
The refresh value, you'll remember, controls how often a slave checks whether its zone data is up to date. The retry value then becomes the refresh time after the first failure to reach a master name server. The expire value determines how long zone data can be held before it's discarded, when a master is unreachable. Finally, on pre-BIND 8.2 name servers, the default TTL sets how long zone information may be cached. On newer name servers, the last SOA field is the negative caching TTL.
Suppose we've decided we want the slaves to pick up new information every hour instead of every three hours. We change the refresh value to 1h in each of the zone data files (or with the -o option to h2n). Since retry is related to refresh, we should probably reduce retry, too -- to every 15 minutes or so. Typically, retry is less than refresh, but that's not required.[64] Although lowering the refresh value will speed up the distribution of zone data, it will also increase the load on the name server being loaded from, since the slaves will check more often. The added load isn't much, though; each slave makes a single SOA query during each zone's refresh interval to check its master's copy of the zone. So with two slave name servers, changing the refresh time from three hours to one hour will generate only four more queries (per zone) to the primary master in any three-hour span.
[64]Actually, BIND 8 servers will warn you if refresh is set to less than 10 times the retry interval.Of course, if all of your slaves run BIND 8 or 9 and you use NOTIFY, refresh doesn't mean as much. But if you have even one BIND 4 slave, your zone data may take up to the refresh interval to reach it.
Some older versions of BIND slaves stopped answering queries during a zone load. As a result, BIND was modified to spread out the zone loads, reducing the periods of unavailability. So, even if you set a low refresh interval, your slaves may not check exactly as often as you request. BIND 4 name servers attempt a certain number of zone loads, and then wait 15 minutes before trying another batch. On the other hand, BIND 4.9 and later may also refresh moreoften than the refresh interval. These newer BINDs wait a random number of seconds between one-half the refresh interval and the full refresh interval to check serial numbers.
Expiration times on the order of a week are common -- longer if you frequently have problems reaching your updating source. The expiration time should always be much larger than the retry and refresh intervals; if the expire time is smaller than the refresh interval, your slaves will expire their data before trying to load new data. BIND 8 will complain if you set an expire time less than refresh plus retry, less than twice retry, less than seven days, or greater than six months. (BIND 9.1.0 doesn't complain yet.) Choosing an expire time that meets all BIND 8's criteria is a good idea in most situations.
If your zone's data doesn't change much, you might consider raising its default TTL. Default TTLs are commonly a few hours to one day, but you can use longer values. One week is about the longest value that makes sense for a TTL. Longer than that and you may find yourself unable to change bad, cached data in a reasonable amount of time.