Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk10 min

How to Set Up Expires Headers on Apache

A practical Apache guide to Expires and Cache-Control max-age: configure mod_expires, build MIME-type policies, choose cache lifetimes, verify responses, and fix common problems.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Apache’s mod_expires module to generate an Expires header and the matching max-age directive in Cache-Control. Turn the module on with ExpiresActive On, establish a fallback with ExpiresDefault, and then add MIME-type rules with ExpiresByType. Put the directives in the server, virtual-host, directory, or permitted .htaccess context, then verify a real response’s Content-Type, Expires, and Cache-Control headers.

A practical policy is to let HTML revalidate immediately, give versioned CSS, JavaScript, and image assets a longer lifetime, and use a conservative fallback for anything not covered by a specific rule. The right duration depends on how often a resource changes and whether deployments change its URL.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What Apache expire headers do

HTTP caching relies on response metadata. Apache’s mod_expires module calculates an expiration time and writes it into two related response headers:

  • Expires contains an absolute HTTP date.
  • Cache-Control: max-age=... expresses the same freshness lifetime in seconds.

The Apache documentation describes the module as controlling both the Expires header and the max-age directive of Cache-Control. You configure a policy; Apache applies it when the response matches the configured criteria.

Why both headers appear

Expires is the older date-based mechanism. max-age is the relative lifetime used by modern HTTP caches. With mod_expires, a single rule normally produces both values, so clients that understand either mechanism receive a usable freshness instruction.

What the headers do not decide

Expire rules do not rename files, purge already cached objects, or decide whether a deployment changes an asset URL. They only describe how long a matching response can be considered fresh. Your policy must therefore account for the way your site publishes changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prerequisites and configuration scope

Confirm that mod_expires is available

The directives in this guide belong to mod_expires. If Apache reports an unknown directive, the module is not loaded or the hosting plan does not expose it. On managed hosting, ask the provider to enable the module or place the rules in the configuration scope it permits.

Understand where directives can be placed

ExpiresActive is valid in server configuration, virtual-host configuration, directory context, and .htaccess. Apache documents the Indexes override class for use in .htaccess, so a host must permit that override class before these directives can work there. A rule in a virtual-host file does not automatically make the same rule available in an unrelated virtual host.

Remember the default state

ExpiresActive is Off by default. Defining an ExpiresDefault or ExpiresByType rule without turning the feature on will not generate the headers.

A minimal .htaccess configuration

If your host allows the required override class, place a policy like this in the document root’s .htaccess file:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ExpiresActive On

# Conservative fallback for content without a specific rule
ExpiresDefault "access plus 1 hour"

# Revalidate HTML frequently
ExpiresByType text/html "access plus 0 seconds"

# Longer lifetime for assets whose URLs change when they are deployed
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType image/* "access plus 1 month"

# A specific image rule overrides the image wildcard
ExpiresByType image/gif "access plus 1 week"

The fallback applies when no more specific MIME-type rule matches. HTML receives a zero-second lifetime, which tells caches to revalidate rather than keep it fresh for an extended period. CSS, JavaScript, and image responses receive a month under the example policy, while GIF files receive one week because the specific rule is more restrictive than the wildcard.

When .htaccess is the wrong place

If the server rejects the file, move the same directives into the virtual-host or directory configuration and reload Apache through your normal administration process. Shared hosts often disable particular overrides; that is a configuration limitation, not evidence that the syntax itself is invalid.

Build a policy with ExpiresDefault and ExpiresByType

Start with a fallback

ExpiresDefault supplies the default expiration algorithm. It protects responses that do not have a dedicated type rule, so the policy has a defined result instead of depending on an accidental server default. A short fallback such as access plus 1 hour is conservative for miscellaneous content.

Add rules for known MIME types

ExpiresByType selects a response by its MIME type and sets both its Expires value and its Cache-Control: max-age. The rule only operates when ExpiresActive On is enabled. Matching is based on the response’s actual Content-Type, not merely the filename extension.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Match Directive value Resulting policy
Fallback access plus 1 hour One hour for responses without a matching type rule
text/html access plus 0 seconds Immediate revalidation for HTML
text/css access plus 1 month One month for CSS
application/javascript access plus 1 month One month for JavaScript served with this MIME type
image/* access plus 1 month One month for image subtypes not covered by a more specific rule
image/gif access plus 1 week One week for GIF responses

Match the server’s real Content-Type

A JavaScript file may be named with a familiar extension but still fail to match if the server sends a different MIME type. Inspect the response and write the rule for the value Apache actually emits. The same check applies to HTML, CSS, images, fonts, JSON, and any other resource category you configure.

Readable and numeric expiration syntax

Readable relative expressions

The readable form uses access or now, or uses modification, followed by an interval. Apache accepts intervals such as years, months, weeks, days, and hours. Examples include:

ExpiresDefault "access plus 1 hour"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 month"
ExpiresByType image/gif "access plus 1 week"

These expressions are calculated when Apache handles the response. The word access means the calculation is relative to the request time; modification uses the resource’s last-modified time instead.

Numeric seconds with an A or M prefix

You can express a lifetime as seconds with a base letter. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ExpiresByType text/html M604800

The M prefix bases the calculation on modification time. An A prefix bases it on access time. The value 604800 is a seven-day interval expressed in seconds. Numeric syntax is compact, while the readable form makes a configuration easier to audit.

Choosing the base time

Base Calculation anchor Useful when
A or access The time Apache serves the response You want a fixed freshness window starting with each request
M or modification The resource’s modification time The file timestamp should determine the expiration date

Choose one deliberately. Switching from access-based to modification-based calculation can materially change the resulting date even when the interval text is identical.

Understand rule precedence

A matching ExpiresByType rule takes precedence over ExpiresDefault. A wildcard major-type rule such as image/* is considered before Apache falls back to the default. A more specific rule can then override the wildcard for a particular subtype, as image/gif does in the example policy.

  1. Apache determines the response’s MIME type.
  2. It looks for a specific type rule.
  3. If no specific rule applies, it can use a matching wildcard major-type rule.
  4. If neither exists, it uses ExpiresDefault.

This precedence lets you define a broad image policy while shortening or extending the lifetime of one subtype. Keep related rules together and comment exceptions so a later administrator can see why a specific type differs from its wildcard.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose lifetimes around your deployment model

HTML and other frequently changing documents

Documents that change often should have a short revalidation window. The example sets text/html to access plus 0 seconds, which avoids treating the document as fresh for an hour or a month. A short lifetime is especially useful when the same URL must show updates promptly.

Versioned static assets

CSS, JavaScript, and image files can use a longer lifetime when deployment changes their URLs. A filename or URL that changes with each new asset version gives caches a new object to request, allowing the old object to remain fresh without hiding the update at the new URL. The example uses one month for these categories.

Unversioned assets

If a file keeps the same URL after its contents change, a long expiration can delay the update for users whose caches still consider the old response fresh. Use a shorter interval or adopt URL versioning before extending the lifetime.

There is no universal best duration

The Apache directive reference defines how durations are generated but does not prescribe one cache lifetime for every site. Base the interval on how often each resource changes, whether URLs are versioned, and how quickly a deployment must become visible. Apply the policy per MIME type rather than assigning one aggressive value to every response.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify the headers on a real response

After changing configuration, test an actual URL that serves the resource type you intended to match. Do not rely only on the presence of a directive in a file.

Use browser developer tools

  1. Open the page in a browser and open Developer Tools.
  2. Select the Network panel and reload the page.
  3. Choose the HTML, CSS, JavaScript, or image request you want to inspect.
  4. In the response headers, record Content-Type, Expires, and Cache-Control.
  5. Confirm that Cache-Control includes the expected max-age and that the MIME type matches the rule you wrote.

Inspect headers from a shell

An HTTP header request makes the same check without rendering the page:

curl -I https://www.example.com/

Replace the path with a real HTML document or static asset on your server. Repeat the request for each category that has a distinct rule. Compare the observed Content-Type with the directive and check that both expiration headers are present when no other component supplies them.

Interpret the result

  • An HTML response governed by the example should show a zero-second max-age calculation.
  • A CSS, JavaScript, or general image response should show the month policy when its MIME type matches.
  • A GIF response should use the one-week specific rule rather than the month-long image wildcard.
  • A response with an unrelated MIME type should use the one-hour fallback if no other header source intervenes.

Why Expires headers may be missing or unchanged

ExpiresActive is still off

Because the default is Off, every policy needs ExpiresActive On in the same applicable configuration scope. Check for spelling, placement, and whether the request is handled by the virtual host you edited.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

No default or MIME rule matches

ExpiresActive On does not promise a header for every response. Apache still needs either a matching ExpiresDefault or an applicable ExpiresByType rule. Add a fallback, correct the MIME type, or both.

The response has a different Content-Type

A type rule is selected from the response MIME type. If the server sends a value other than the one in your directive, the rule will not match. Use the Network panel or an HTTP header request to identify the exact value and configure that value.

Another component already generated the headers

When an Expires or Cache-Control header already comes from Apache’s other processing, a CGI script, or a proxied origin response, mod_expires does not change or add that header. In this case, inspect the upstream or application configuration that produced it instead of adding more mod_expires rules.

.htaccess overrides are not permitted

If Apache returns a configuration error after you save the file, the host may not permit the required override class in that directory. Move the directives to a server, virtual-host, or directory configuration where you have permission, or ask the administrator to enable the documented override class.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You tested a different request than the one you configured

Rules are evaluated per response. Test the exact asset URL and check its MIME type; a page request and an image request can legitimately receive different policies.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Configuration examples for common layouts

One shared policy in a virtual host

When you control the virtual-host configuration, place the directives inside the appropriate host or directory context:

ExpiresActive On
ExpiresDefault "access plus 1 hour"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType image/* "access plus 1 month"
ExpiresByType image/gif "access plus 1 week"

This gives the host one predictable fallback and explicit exceptions. Keep the policy in the configuration scope that actually serves the requested virtual host.

A narrowly targeted directory policy

A directory-level configuration can apply a different policy to a section of a site, provided that the directives are allowed in that context:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ExpiresActive On
ExpiresDefault "access plus 1 hour"
ExpiresByType text/html "access plus 0 seconds"

Use a narrower scope when only one directory needs the behavior. Remember that the response still has to match the MIME rule or inherit the directory’s fallback.

A deployment checklist

  • Confirm that mod_expires is loaded and that your configuration scope accepts its directives.
  • Set ExpiresActive On; it is off by default.
  • Define ExpiresDefault so unmatched responses have a deliberate fallback.
  • List the MIME types you actually serve and verify their Content-Type values.
  • Use short revalidation for HTML or other URLs that must reflect changes quickly.
  • Use longer lifetimes for static assets only when deployment changes their URLs or another reliable invalidation method exists.
  • Use a wildcard such as image/* for a broad policy and add specific overrides for exceptions.
  • Choose access versus modification based on the time anchor your deployment needs.
  • Request real responses after editing and inspect Content-Type, Expires, and Cache-Control: max-age.
  • If headers remain unchanged, look for an existing header from Apache processing, a CGI script, or a proxied origin.

Common mistakes to avoid

Turning on the module but setting no policy

ExpiresActive On enables generation; it does not select a duration by itself. Pair it with a default or type-specific rule.

Assuming filename extensions control matching

Apache evaluates the MIME type sent in the response. A rule for application/javascript cannot match a response that is actually labeled with another type.

Putting a long cache lifetime on mutable URLs

A month-long policy is appropriate for assets whose URLs change with deployment, not automatically for every file ending in .css, .js, or an image extension. If the URL stays constant, choose a shorter lifetime or change the publication strategy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Expecting mod_expires to override an application header

Existing Expires or Cache-Control headers from the server, a CGI script, or a proxy are not replaced by mod_expires. Find and adjust the component that emitted the original header.

Ignoring precedence

A specific MIME rule wins over the fallback, and a specific subtype can override a wildcard major type. Review the complete set of rules when a response appears to have a shorter or longer lifetime than expected.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.