(Note to future readers: This is fixed in WordPress 3.3, so this article is now out-of-date. See http://core.trac.wordpress.org/changeset/18541 for the patch.)

I was not aware that other people didn’t know about this until recently, but since it seems to be little known, I thought I’d write a post on the topic.

Chain LinksIn WordPress, you should never start the custom permalink string with any of these %postname%, %category%, %tag%, or %author%. (Unless you know what you’re doing, of course. :) )

Meaning that “%category%/%postname% ” is a bad custom permalink string. So is just “%postname%” for that matter.

Why? Well, it has to do with how the WordPress Rewrite system works.

Rewriting Explained

See, when you request a URL from a WordPress site, WordPress gets the URL and then has to parse it to determine what it is that you’re actually asking for.

It does this by using a series of rules that are built whenever you add new content to WordPress. Generally the list of rules is pretty small, but there are specific cases that can cause it to balloon way out of control.

Normal Rules

Let’s say you’re using a normal permalink string, like my preferred “%year%/%postname%”. The rules that are generated will look like this:

/robots.txt (for the privacy settings)
/feed/* (for normal feeds of any kind)
/comments/* (for comments feeds)
/search/* (pretty url for searches, not often used)
/category/%category% (category archives)
/tag/%tag% (tag archives)
/author/%author% (author archives)
/%year%/%month%/%day% (with each of those after year being optional)
/%year%/%postname% (this is the permalink string you define)
/%pagename% (any Page)

The way that system works is that it compares the URL it has to each of those in turn, from the top to the bottom. When one of them fits, then WordPress knows what to display and how to do it.

Note that the order I listed those in is is significant. Each one from the top down is less specific than the previous one.  For example, “robots.txt” matches only that, while “/feed/*” matches anything starting with /feed/. And so on down the list. The %postname%, %category%, %tag%, %author%, and %pagename% will match any string, but the other WordPress % ones will only match numeric fields. Like %year% is always a number.

Notice that the last one is %pagename%. This basically matches everything, because %pagename% can be anything at all. Even hierarchical pages like /plugins/whatever/something will cause this to match. It’s the fall-through position. And then, if that page doesn’t actually exist on your site, then this causes the query to trigger the 404 condition internally, which causes your theme’s 404.php to load up.

Pretty simple and straightforward, really.

Problem Rules

The problem comes in when you try to use a non-number for the beginning of your permalink string. Let’s examine those last two rules closer:

/%year%/%postname% (this is the permalink string you define)
/%pagename% (any Page)

What if you used “%category%/%postname%” for your custom permalink string? Now those last two rules are these:

/%category%/%postname% (this is the permalink string you define)
/%pagename% (any Page)

That violates our main rule, doesn’t it? That each one should be less specific than the one above it? Because %category% can match any string too, just like the %pagename% can… With this set of rules, there’s no way to view any of the Pages. Not good.

So, WordPress detects this condition and works around it. Internally, this sets a flag called “use_verbose_page_rules”, and that triggers the rewrite rebuild to make this set of rules instead:

/robots.txt (for the privacy settings)
/AAA
/BBB
/CCC (one of these for each of your Pages)
/feed/* (for normal feeds of any kind)
/comments/* (for comments feeds)
/search/* (pretty url for searches, not often used)
/category/%category% (category archives)
/tag/%tag% (tag archives)
/author/%author% (author archives)
/%year%/%month%/%day% (with each of those after year being optional)
/%category%/%postname% (this is the permalink string you define)

Now we have basically the same set of rules, except for those new ones at the top. Every Page now gets its own very specific rule, and this satisfies our main condition once again.

Pages

But what if you have a lot of Pages? I once read a post by a person who had over 50,000 Pages on his site. That is a special case obviously, but consider our lookup system. We’re going through these rules one at a time. With our first method, our rule list was only 10 rules, maximum. With this new method, you add a rule for every single Page you make. Going through 50,000 rules takes a lot longer than going through 10. And even just building that list of rules can take a long time.

Basically you’ve created a performance issue. Your Pages now won’t scale to unlimited numbers. Your site’s speed is linearly dependent on the number of Pages you have.

This is a bad thing.

Conclusion

Firstly, it’s really not any better for SEO to have the category in there, or to have just the postname there by itself. And anybody who tells you differently is wrong. If you disagree with me, then no, I’m not interested in arguing this point with you; you’re just wrong, period, end of discussion.

Secondly, shorter links are great and all, but hell, why not use a real shortlink? WordPress 3.0 now has a ShortLink API that defaults to using ?p=number links on your own domain. These will actually work for any WordPress site, even ye back unto WordPress 2.5. WordPress 3.0 just makes it nicer and easier to use these with the Shortlink API (as well as allowing plugins to make this automagically use services like wp.me or bit.ly). So use that instead.

The conclusion is, in general, just don’t do it. Leave a number, or something static, at the beginning of your permalink string and you’ll never have any sort of problems. But if you really MUST do this sort of thing, then keep your number of Pages low. Don’t try it when you have more than, say, 30-50 Pages.

Addendum

Okay, so I actually simplified things for this post. It’s actually worse than this, as verbose page rules can add much more than one rule per page, as this post demonstrates (he gets 11 per extra page!).

Shortlink:

291 Comments

  1. For my post url structure i’m using /%post_id%/%postname%/ So I know I’m doing good on that front.

    However, I am currently using a seo plugin that gives me this option: “Strip the category base (usually /category/) from the category URL.”

    My category archive pages went from looking like site.com/category/some-category-name/ to site.com/some-category-name/

    My question is will using this category base removal on archive pages hurt site performance? I expect to have less than 10 categories, but I may have a lot of pages.

    Thank you!

  2. I see that this was asked previously but not answered; does this also apply to Custom Post Type permalinks?

    For a site I’m working on, I have a CPT named “music” and by default WP creates a Custom Permalink: /%post_type%/%music%/

    Is that wrong? Should it be something like /%post_id%/%post_type%/%music%/ instead?

  3. Otto says:
    May 4, 2011 at 11:33 am
    No, that’s fine. Custom post types aren’t affected in any real way by this sort of thing.

    Are you saying that CPT doesn’t have anything to do with “use_verbose_page_rules” ?

    • yep, my understanding (from what I have read) is that wordpress is forced to turn this on if the START of the permalink is difficult to resolve – ie. /postname/*
      /category-name/*
      /tag-name/*
      /author-name/*

      ..and that is where the stuff hits the fan .. sometimes :)

  4. I maintain several blogs where i’ve been using /%postname%/ as custom permalink for posts (I guess the pages, too, though there are only ‘about’ and ‘contact’ pages).

    I never noticed ‘the fine print’ when I set them up originally, even wordpress codex ( http://codex.wordpress.org/Using_Permalinks ) says that it’s not recommended (“Starting Permalinks with %postname% is strongly not recommended for performance reasons..” and then repeats the statement for category, tag and author). I must admit, I haven’t noticed these statements before, although I’m sure I read the page when I was new to wordpress.

    the problem is these blogs have been around for more than a couple of years and I’m just wondering about changing all the links suddenly, say instead of just /%postname%/ to posts/%postname%/ or /%year%/%postname%/ — my concern is search engines, obviously.

    I have to ask the owners of the blogs I maintain what they want me to do and I’m wondering what your thinking about this problem and if there is a rewrite solution that wouldn’t make things worse.

    thanks, — s

  5. Just putting a new wordpress site together…a newbie! Have read a lot on this subject. Would it work, or be advisable, to set up categories with numbers. For example: /your site/101-catetory-name/post-name. Would this take care of the issue of having a number first. Each category would then be preceded by it’s own number. 101,102,103…that sort of thing. Rather than a random id number.

    • I am a newbie on WP as well and ran across too many redirects, an error message told me the same thing. I went back to WP and looked for a solution since I got no satisfactory answer from the forums (that is not to say it has not been covered somewhere below here, but): If you simply go with the numeric option for your posts or pages you will have success at least 95% of the time.
      This may not be the best way and some wise sage here undoubtedly knows a better way to do this.
      Although, for me, a newbie, where all my pages had ended up with the too many redirects error page appearing, and not knowing just where to place the code, let alone understand some of it (newbie), this has worked for me almost flawlessly. I have very few posts on the website, there are about 30 pages right now with another 30+ more coming up for an online store.
      I hope this helps.

  6. Better ask in this forum…

    I have just heard this:
    The (pretty) permanent link structure you define is in addition to the default ?p=blah format that WordPress uses.

    Is that true ? Well, if it’s true… then there should be no problem using %postname%

  7. […] you are interested in the bloody details, then you should read this article by Otto, a well-known expert on […]

  8. Hi. I developed a site.
    http://www.chicagopolicemisconductlawyer.com

    I was able to change all of the permalinks on the pages to custom ones.

    I am basically using wordpress as a CMS but I have a page titled “NEWS” and use it as a blog. When I make a new post entry I can’t find a way to change the post permalink to something friendly.
    I have three posts so far and they all show in the sitemap as
    http://www.chicagopolicemisconductlawyer.com/%/postname%

    plesae see my site map below
    http://www.chicagopolicemisconductlawyer.com/sitemap.xml

    I would ideally like to have the /%/postname% be the title of the post.

    Thank you for your help.

  9. I’ve just started working on my travel blog. From an organisational perspective, I thought that domain/travel/%country%/date/postname made the most sense. I was going to retrieve “country” using %category%, but going by what I am reading here, it’s not a good idea.

    What if I hardcode country? It’s a hassle because I need to remember to edit it every time I write about a new place, but would that like me do, for instance, /%postname%? Or would I still need to fit a number between the hardcoded country and %postname%?

    Thanks!

  10. […] it because it is unfriendly to users in the many contexts in which users interact with URLs.) See Otto’s technical writeup on the topic as well as this wp-testers […]

  11. […] it because it is unfriendly to users in the many contexts in which users interact with URLs.) See Otto’s technical writeup on the topic as well as this wp-testers […]

  12. So I was wondering if starting with a word like /posts/ would fix the performance problems, I was thinking something like /posts/%category%/%postname% would this still face the same performance issues? They suggested something like this on the wordpress site.

    • Yes, that would be fine. I would prefer /posts/%page_id%/%category%/%postname% as I think that will require fewer database lookups to resolve, but anyways yours should still work quickly enough.

  13. Hi Otto, this article was really useful, but I’m missing something because I’m trying to solve my problem by following your advice and nothing seems to work. I have a website made mainly of pages (non time sensitive date) and I have a blog to announce every new article that I publish. The number of pages will scale to around 1000 (it’s a touristic guide). I’m trying to use /%year%/%postname%/ as you suggest, but the year does not show up before the name of the pages in the URLs, only before posts. Tried /%page_id%/ with no luck. Can you please put me in the right direction? Thanks!

    • The custom permalink string only applies to Posts, not to Pages. So what you’re describing is correct, and intentional.

      The problem is when you have a lot of Pages and a *bad* permalink string. If the permalink string is good, you have no problems.

      • Hi Otto,

        Thanks a lot for replying. Sorry to bother you, but I am trying to understand this properly. I’m planning to scale this website up to around 1000 pages. Can you please tell me what a good permalink string would be for my pages? Or maybe I should consider not using pages but posts?

        • Sorry Otto, I read again what you wrote and I didn’t understand at first glance. You mean that the custom permalink structure applies only to posts and not pages (which are always ‘called’ by the page’s title). So if I have a good permalink string (for posts that is) as /%post_id%/%postname%/ I will have no problem because WP will be able to differentiate between posts and pages. So I can also have a 500 pages website as far as the permalink string is *good*. Is this correct? Did I understand this properly? Thanks a lot for helping out. :)

  14. […] the parameter based default or a long date based URL.Samuel Wood's great post on the subject (http://ottopress.com/2010/catego…) points out some of the reasons that it affects performance while dismissing the impact the address […]

  15. […] I decided to keep that post structure i.e. janetalkstech.com/%postname%. Unfortunately for me, WordPress developers strongly recommend against setting up sites this way. After several days of seeing intermittent 500 […]

  16. HI Otto,

    Thanks for this information. I agree, it’s a topic that isn’t often brought up. Here’s my question…

    Is there anything wrong with keeping the Post ID and Post Name together rather than having them in separate sub folders. In other words, would it be ok to separate the two entries with an underscore to reduce the number of subdirectories down?

    /%post_ID%_%postname%

    Or is that just plain dumb? :-)

  17. I´m using year, mounth and postname… it´s correct?

  18. hi
    /%postname%/ dont work on one of my blogs, it just gives me the post id instead of post name , can you help me with this ?

  19. I read wordpress permalink article from http://codex.wordpress.org/Using_Permalinks and that refer to your site. umm I see this issue “Starting Permalinks with %postname% is strongly not recommended for performance reasons.. ” (same thing for start permalink with %category%,%tag%, %author%)

    what is the best permalink structure ? http://example.com/?p=N ?

    All of blogger ever read and belive permalink is importance for SEO traffic ( use /%posrname% in permalink ) ; what you think about this belive ?

  20. […] or some other numerical value to help WordPress differentiate between pages and posts. You can read the debate here and make up your own […]

  21. I have been creating pages for the, About, Contact, Privacy Policy, Services and such; basically static pages where the content will rarely change. I have been leaving the permalink structure on default so I get something like this:
    http://beastupathletics.co/?page_id=16
    when I click on it not only does it take a long time but all I get the message that the browser could not open the page due to there being too many redirects which redirected to the original page.
    Would it make more sense to just click the option for numeric, such as:
    beastupathletics.co/2_about

  22. […] being said, there’s a great post on Otto on WordPress explaining the above and even offering that if you’ll keep your site’s pages to no more than […]

  23. […] stop reading now. Otherwise, you will want to read Otto’s very well explained post on why certain permalink structures are more harmful than others. Seriously read it now. No time to read it? Ok, basically WordPress keeps it’s rewrite rules […]

  24. Hello,

    As I’am currently building my first website with wordpress 3.2, I’ve read the article with great interest but I’m left with one important question and I can’t seem to find the answer anywhere : what about custom post-type permalinks?
    By default, their permalink structure starts with the name of the custom post type, ie with a string, which is said to be harmful in this article.
    As I plan to make a big use of custom post types on that web site, will I be runnning into performance issues because of the permalinks?
    Any hints about this will be appreciated.

    Thanks

  25. wow Otto…this I never knew…I was pointed at your information and now I have to change my beliefs that the category or postname in the url are useless…hmmm…I wonder if changing things will lead to trouble for getting lots of backlinks not recognized anymore or something…

    I might try it on a couple of my sites ( http://www.bestautomaticbreadmaker.net and http://www.overcomingpanicattackshelp.com) differently and see what happens, but it kinda blew me away…YOu see this is the kind of information you “pick up” by complete coincidence. I consider myself lucky perhaps :)

    Thanks for this helpful post.

  26. Hi Otto and readers,

    I am launching a new WP based “Classipress” site – that sort of functions like a craigslist – but not quite. Because it will have multiple categories / and subs of those – may 5 X 6 so 30 ‘ish (My plan is to have a site just for jobs – so categories and then subs of those)thus I will “hopefully” have a lot of pages if successful. Knowing this – could you please render me your recommendation of what YOU would choose as a good permalink / structure? Obviously speed and efficiency will be an issue so using IIRF (the site will be hosted on a Windows server) in combination with a good permalink strategy from the very start is very important.

    Thank you very much and great info in here.

    Mark

  27. […] things here and there over the years that this has been a problem. One of those articles was on “Otto on WordPress” which delves into […]

  28. I’ve read in the comments that custom-post-type permalinks aren’t worrisome.

    For reasons of consistency, I’ve added the post-ID to the beginning of my custom-post-type pages via the filters post_link & post_type_link.
    Would this compromise the load-speed of my site? Or is this beneficial/moot?

    Thanks!
    -Michael

  29. […] Details are also present in the Codex page about Using Permalinks and also on Otto on WordPress. […]

  30. […] – changing the links to be postID/postname fixes this. For a detailed explanation on why see here. var disqus_url='http://www.designed-by-robots.com/231/turbo-charging-wordpress/';var […]

  31. […] comes in. Unfortunately, the permalink I describe above can make WordPress run slowly (I found this post helpful for the reasons why although it gets pretty […]

  32. […] http://www.weberz.com/blog/wordpress/seo-experts-give-wrong-advice-wordpress-permalinks/http://ottopress.com/2010/category-in-permalinks-considered-harmful/ 2. Make sure to verbosely define any Custom Post Types, read up on the latest Permalink settings for them in each of the newer WordPress 3.x versions. 3. Register your Javacript and CSS with WordPress correct using wp_enqueue_script() and wp_enqueue_style(). 4. Follow WordPress guidelines for querying/displaying posts! This is vital, as PilotPress interacts with the filtering mechanism. 5. Do NOT use header() calls, use wp_redirect(). Additionally, don’t HARDCODE any paths, use get_permalink() and site_url() functions. This entry was posted in Payment Processing and tagged permanently, PilotPress by Will. Bookmark the permalink. […]

  33. Hi Otto,

    It was nice meeting you at WordCamp Chicago 2011.

    Thanks for the info on permalinks. I have a question.

    I have changed permalinks from /%postname%/ to /%post_id%/%postname%/. As you said, too many pages. I had no choice, too many 404 errors.

    Since the site I’m working on is indexed, how do I avoid using a plugin and write the change in .htaccess to redirect the old structure (above) to the new?

    Thanks,

    Regina Smola

  34. […] was reading an article about the “bad” use of %category% in wordpress permalinks and it sounds reasonable not to use this combination ( “%category%/%postname%” ). There was an […]

  35. […] was reading an article about the “bad” use of %category% in wordpress permalinks and it sounds reasonable not to use this combination ( “%category%/%postname%” ). There was an […]

  36. If i use structure /blog/%category%/%postname%/ , it is normal?

  37. […] much head scratching I would go with Sarah’s advice. She is basing it on this post by Otto on WordPress and I think he makes a convincing argument. The thing is, so long as you make sure you include […]

  38. […] información cómo el nombre del post o indicar la categoría de lo que en él se habla. En este enlace podeís leer más del […]

  39. Hey everyone,

    i have problems with my multside enabled wordpress installation and all blogs with static frontpages.

    The problem is simple that all posts are shown as pages.

    I have a “home”-page and a “blog”-page

    All “pages” are under http://www.endlichschlanksein-coaching.de/about or http://www.endlichschlanksein-coaching.de/impressum and this is okay.

    all blog posts (articles not pages) should be under http://www.endlichschlanksein-coaching.de/blog (because i set it under static page settings) and are shown under this http://www.endlichschlanksein-coaching.de/blog. In my case i see all 3 test articles.

    If want read the complete post (and klick read more, or article headline) what should happen? the browser should go to the adress http://www.endlichschlanksein-coaching.de/blog/hello-world

    but in my case it goes to

    http://www.endlichschlanksein-coaching.de/hello-world/

    why? because its not a page!!! its a blog article.

    This problem exists only with the multisite installation. some years ago, as i installed wordpress without multisite-support there was not this problem.

  40. […] it because it is unfriendly to users in the many contexts in which users interact with URLs.) See Otto’s technical writeup on the topic as well as this wp-testers discussion. About admin Did you love this post? Tell […]

  41. […] information like the post name or some important words related to the post itself. In this link we can read more about […]

  42. […] it because it is unfriendly to users in the many contexts in which users interact with URLs.) See Otto’s technical writeup on the topic as well as this wp-testers discussion. October 30th, 2011 | Category: […]

  43. […] it because it is unfriendly to users in the many contexts in which users interact with URLs.) See Otto’s technical writeup on the topic as well as this wp-testers […]

  44. […] are planning on creating a website of more than 30-50 pages then it is a bad idea as stated over at ottopress.com. This is a trusted source which is actually cited at […]

  45. This /%posttype%/ permalink structure is no longer an issue with the upcoming WordPress 3.3, according to the newly listed features of the beta version. This permalink structure is actually even listed as a permalink option. Sweet indeed.

  46. I’m wondering what might impact the .htaccess file/coding generated by WP. After customizing my permalinks, I ftp the new .htaccess and everything works well for 24 hours and then the pages and posts start displaying incorrect mismatched text.

    – it’s not a plugin issue
    – it’s not a local cache issue on my machine

    I’ve done some internet reading and any talk of incorrect displays suggest loading a blank .htaccess and then reloading the WP generated .htaccess. This works for me for about 24-48 hours and then stops working.

    If you have any ideas on what might influence my .htaccess file, please let me know.

    My permalinks are set as /travel/%postname%-%post_id%/ for my travel blog.

    thank you
    Tracy

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Need to post PHP code? Wrap it in [php] and [/php] tags.