Recruitment website development engineered for speed and scale

Most recruitment websites fail on the pages that matter most commercially: the job listing and the job detail page. They are built as an afterthought on top of a generic CMS template, rendered client-side, and left to fetch vacancy data from an ATS with no fallback when that ATS is slow or unavailable. Recruitment website development is a distinct discipline from general web development because the data layer, the indexation strategy and the performance budget all revolve around one volatile, constantly-changing dataset: live vacancies.

We build recruitment sites as engineering projects first and design projects second. That means deciding early how job data moves from your ATS into rendered HTML, how thousands of vacancy URLs get indexed or deliberately kept out of the index, how JobPosting structured data stays valid as fields change, and how the whole thing survives your ATS having a bad day. This page sets out the technical decisions that separate a recruitment website that ranks and converts from one that quietly leaks fee income through slow pages and invisible vacancies.

Written by Joshua Doyle, Founder and Strategy Director, We Are SDM. Published . Last updated . 13 minute read.

  • Rendering approach

    server-rendered job pages by default, not client-fetched JSON

  • ATS resilience

    cached vacancy data so listings survive ATS downtime

  • Structured data

    JobPosting schema validated against every mapped field

  • Indexation control

    deliberate rules for which vacancy URLs Google should crawl

Server-side rendering versus client-rendered job boards

The single biggest architectural decision in recruitment website development is where the vacancy data gets turned into HTML.

A large share of the recruitment sector's job boards were built as single-page applications that fetch vacancy data client-side, after the page has already loaded. That approach is fine for a logged-in dashboard. It is a serious liability for a public job board that needs to rank in search and convert cold traffic. If a search engine crawler or a slow mobile connection sees an empty shell while JavaScript fetches the actual vacancy content, you have handed away both your SEO visibility and a chunk of your conversion rate before the page has even rendered anything meaningful.

We default to server-side rendering or static generation with incremental revalidation for vacancy pages, meaning the job title, description, salary and location are present in the HTML the moment it leaves the server. This is not a stylistic preference, it is what allows a job page to be indexed correctly, to pass Core Web Vitals, and to display something useful to a candidate on a poor connection at a station platform. Client-side rendering still has a role for interactive filtering and saved search features layered on top, but the initial vacancy content itself should never depend on a browser executing JavaScript successfully.

In practice this means choosing a framework and hosting setup that supports hybrid rendering: static or server-rendered for the vacancy detail and listing pages, and client-side interactivity for search refinement, sorting and application forms. Getting this split wrong in either direction either kills your SEO or kills your interactivity, and reworking it after launch is expensive because it usually means restructuring the data-fetching layer, not just the templates.

  • Search-engine visibility

    Rendered HTML means crawlers see the actual job content on first request, without needing to execute and wait for client-side JavaScript to populate the page.

  • Perceived load speed

    Candidates see vacancy content immediately rather than a loading spinner, which matters disproportionately on mobile and on job boards where bounce happens in seconds.

  • Resilience on poor connections

    A server-rendered page degrades gracefully if a script fails to load; a client-rendered page frequently shows nothing at all.

  • Accessibility by default

    Assistive technology reads server-rendered content reliably, whereas dynamically injected content can be missed or announced late by screen readers.

ATS API integration patterns that actually hold up

Almost every recruitment website development project hinges on one integration: pulling vacancy data out of an applicant tracking system and into the public website. There are two broad patterns for keeping that data fresh, polling and webhooks, and most agencies we audit are using whichever one their ATS defaulted to rather than the one that suits their traffic and update frequency.

Polling means the website periodically asks the ATS API, on a schedule, whether anything has changed. It is simple to build and reasonably reliable, but it introduces a lag between a consultant updating a vacancy and that change appearing live, and it can hammer an ATS with unnecessary requests if the polling interval is too aggressive. Webhooks flip the model: the ATS pushes a notification to the website the moment a vacancy changes, which gives near-instant freshness but requires the website to expose a reliable receiving endpoint and to handle malformed or duplicate payloads gracefully, because ATS webhook implementations vary wildly in quality.

In our build process we usually run a hybrid: webhooks for real-time updates where the ATS supports them reliably, with a scheduled polling job as a safety net that reconciles the full dataset periodically to catch anything the webhook missed. This belt-and-braces approach costs a little more engineering time upfront but avoids the single most common recruitment website fault we see in audits, which is a vacancy that was closed in the ATS three weeks ago still sitting live and indexed on the public site, quietly damaging both candidate trust and crawl budget.

Normalised job model

Every ATS structures job data slightly differently: field names, salary formats, location taxonomies and sector categorisation all vary. Building directly against one ATS's raw schema locks the front end to that vendor's quirks and makes a future ATS migration painful. We build a normalised job model, an internal schema that every incoming ATS payload gets mapped into before it touches a template. Salary gets standardised into a consistent structure whether it arrives as a range, a rate or a fixed figure. Location gets geocoded and standardised. This layer is what makes JobPosting structured data, search filtering and multi-brand sites possible without duplicating logic per ATS.

Resilience when the ATS is down

ATS platforms go through maintenance windows, rate-limit clients under load and occasionally fail outright. A recruitment website that fetches vacancy data live on every page request will go down, or show empty listings, the moment the ATS has a problem. We cache the normalised job dataset on our own infrastructure and serve from that cache with a defined staleness tolerance, so the public site keeps functioning, showing the last known good vacancy data, even if the ATS is completely unreachable. This is a small architectural decision that prevents a large and entirely avoidable reputational problem.

Job data quality and field mapping

The quality of a recruitment website's SEO and conversion performance is bounded by the quality of the data feeding it, and most consultancies do not think carefully enough about field mapping until it causes a visible problem. Salary fields are the classic example: a vacancy entered as “neg” or “DOE” in the ATS produces a job page with no visible salary, which both search engines and candidates penalise, the former through weaker JobPosting schema completeness and the latter through lower click-through and application rates.

We map and validate every field that flows from ATS to website against a defined schema before it is allowed to render: job title normalisation so titles are not duplicated with inconsistent casing or trailing whitespace, location standardisation so “London”, “london” and “Greater London” do not create three separate filter buckets, sector and specialism tagging that is consistent enough to power both site navigation and structured data, and salary parsing that flags incomplete entries back to consultants rather than publishing them blank. This validation layer catches the kind of data quality issues that otherwise surface months later as a slow decline in job page rankings that nobody can immediately explain.

Core Web Vitals and why job pages are the hardest to keep fast

Job listing and detail pages are structurally the hardest pages on a recruitment website to keep fast, because they combine everything that tends to hurt performance: dynamic data fetched at request time, filtering and search widgets loaded with client-side JavaScript, third-party application form embeds, and often a job board plugin bolted onto a CMS that was never designed for high page volume. Largest Contentful Paint suffers when the main job content depends on a slow API call. Cumulative Layout Shift suffers when salary badges, apply buttons or related-vacancy widgets load in after the initial render and push content around. Interaction to Next Paint suffers when filtering logic runs expensive re-renders on every keystroke.

Fixing this requires treating job pages as a distinct performance budget from the rest of the site, not an extension of the homepage template. We set explicit budgets for job page weight, defer non-critical scripts such as chat widgets and marketing pixels until after the main content has painted, reserve layout space for elements that load asynchronously so they cannot cause shift, and cache aggressively at the edge so repeat visits and paginated listing pages do not each trigger a fresh data fetch. For a recruitment agency with several thousand live vacancies, the cumulative effect of shaving even a few hundred milliseconds off the job page template is far larger than the same saving on a single about page, because it compounds across every vacancy and every candidate session.

  • Defer non-critical scripts

    Chat widgets, marketing pixels and non-essential trackers load after the main job content has painted, not before or alongside it.

  • Reserve layout space

    Elements that load asynchronously, such as related vacancies or salary insight widgets, get explicit dimensions reserved so they cannot shift content once loaded.

  • Edge caching for listings

    Paginated and filtered listing pages are cached at the edge with sensible invalidation rules, avoiding a fresh ATS fetch on every visitor request.

  • Image and asset discipline

    Consultant photos, employer logos and hero imagery are served at appropriate sizes and formats rather than full-resolution originals scaled down in the browser.

Indexation control for large vacancy sets

Recruitment agencies with high vacancy turnover run into a specific SEO problem: publishing thousands of job pages, many of which are near-duplicates, filled with thin content, or live for only a few days before the role is filled. Left unmanaged, this produces exactly the kind of low-value, high-volume indexation that search engines are increasingly sceptical of, and it can drag down the perceived quality of an entire domain even though each individual page is legitimate.

Indexation control means making deliberate decisions rather than letting every URL the ATS generates get crawled and indexed by default. Vacancies that are duplicated across multiple sector or location taxonomy pages need canonical tags pointing to a single authoritative URL. Vacancies filled or expired should be redirected or noindexed rather than left as dead pages returning a soft 404. Extremely thin vacancy listings, where a client has provided almost no description, should either be enriched with consultant-written context or kept out of the index until they are. We also manage crawl budget deliberately through XML sitemaps segmented by freshness, so search engines prioritise crawling the vacancies most likely to have changed rather than re-crawling a static archive of long-closed roles.

Handling expired vacancies

What happens to a job page after the role is filled matters more than most agencies assume. A hard 404 loses any accumulated ranking signal and frustrates candidates who followed a link from a job alert email or a job board. A blank “this vacancy has expired” page with no further value gets indexed as thin content. Our default is a 302 redirect to a live, closely related vacancy or to the relevant sector listing page, preserving the visit rather than losing it, combined with structured data updates that mark the JobPosting as no longer valid so search engines stop surfacing it in job-specific results.

JobPosting structured data done properly

JobPosting schema is one of the few structured data types with a direct, visible payoff: correctly implemented, it makes a vacancy eligible for Google's job search features, which sit above standard organic results and carry meaningfully different click behaviour. Getting it wrong is common because the schema has strict requirements around required fields, valid date formats and salary structuring, and a normalised job model that changes over time can silently break compliance if nobody is validating it.

We treat JobPosting schema as a generated artefact of the normalised job model, not a hand-maintained template, so that every field required for validity, title, description, date posted, valid-through date, employment type, hiring organisation and location, is populated automatically from the same data that renders the visible page. Salary is included wherever the client has provided one, because incomplete salary data is one of the most common reasons job schema gets rejected or under-utilised. We validate schema against Google's testing tools as part of the QA process for every launch and set up ongoing monitoring so a future ATS field change or template edit does not silently break markup that was working correctly at launch.

Security and candidate data handling

A recruitment website collects personal data at volume: CVs, contact details, salary expectations, sometimes right-to-work and diversity monitoring information. This puts it squarely within UK GDPR obligations and, for agencies working internationally, potentially other data protection regimes as well. Security is not a bolt-on feature here, it shapes how forms are built, how CVs are stored, and how long candidate data is retained before it is either deleted or subject to renewed consent.

Our build process includes encrypted storage for uploaded CVs and application data, secure transmission to the ATS or CRM rather than storing sensitive files on the website's own server longer than necessary, and clear consent capture at the point of application that matches what the agency's privacy policy actually states. We also apply standard web application security practice: dependency updates kept current, admin access restricted and logged, and form endpoints protected against automated spam and scraping, which recruitment sites attract at higher rates than most sectors because of the perceived value of CV databases to scrapers.

  • Encrypted storage

    CVs and application data are encrypted at rest and in transit, not stored as plain files accessible via a predictable URL structure.

  • Retention discipline

    Candidate data retention periods are enforced technically, not just written into a policy document nobody checks against the database.

  • Consent capture

    Application forms record what a candidate actually consented to, in a way that matches the live privacy policy at the time of submission.

  • Spam and scraping defence

    Form endpoints and CV repositories are protected against automated abuse, which recruitment sites face more of than most other sectors.

QA and launch for high-stakes recruitment sites

A recruitment website launch carries more operational risk than most corporate site launches because the ATS integration, the application funnel and the job feed all need to keep working uninterrupted, often for a business that is placing candidates and earning fee income every single working day. A launch that breaks the vacancy feed for even a few hours has a direct, measurable commercial cost in a way that a broken image carousel on a corporate site does not.

Our QA process for recruitment website development covers the integration layer as thoroughly as the visible front end: testing ATS webhook delivery and the polling fallback under realistic conditions, validating that JobPosting schema passes for a representative sample across every vacancy type the agency posts, load-testing the listing and search pages under expected traffic, and running the full application funnel end to end including what happens when a candidate applies for a vacancy that gets filled mid-application. We stage launches with a rollback plan and monitor the vacancy feed and application volume closely in the first days after go-live, because subtle integration issues often only surface once real ATS updates start flowing through in production rather than in a staging environment with test data.

The We Are SDM recruitment website development process

Our approach to recruitment website development starts with a technical discovery phase focused specifically on your ATS, its API capabilities, its webhook reliability and its data quality, before any design work begins. This determines the architecture: what can be server-rendered, what needs a caching layer, and what indexation strategy suits your vacancy volume and turnover. We would rather spend two extra weeks understanding your ATS's quirks upfront than discover them after launch when they are far more expensive to fix.

Development then proceeds through the normalised job model, the rendering and caching layer, structured data, and the front-end templates, in that order, because each layer depends on the one before it being solid. We involve consultants and marketing stakeholders in reviewing job page templates against real vacancy data, not lorem ipsum placeholder text, because job data has quirks, long titles, missing salaries, unusual location formats, that only show up when you look at the real thing. Post-launch, we monitor Core Web Vitals, indexation coverage and schema validity on an ongoing basis, because a recruitment website's technical health degrades quietly over time as ATS fields change and vacancy volume grows, and catching that drift early is far cheaper than a full rebuild three years later.

Recruitment website development FAQs

Should our recruitment website be server-rendered or a single-page application?

For the vacancy listing and detail pages specifically, server-side rendering or static generation with incremental updates should be the default. These pages need to be indexed reliably by search engines and need to display meaningful content instantly even on a poor connection, and client-side rendering makes both of those harder to guarantee. A single-page application architecture can still work well for interactive elements layered on top, such as filtering, saved searches or a candidate portal, where SEO indexation is not the primary concern. The mistake most recruitment websites make is applying a single-page application approach to the whole site including the job pages, which undermines search visibility for the exact pages that need to rank. A hybrid approach, server-rendered content with client-side interactivity where it genuinely helps, is almost always the right answer for a recruitment website carrying meaningful vacancy volume.

How often should our website pull vacancy data from the ATS?

It depends on how frequently your consultants update vacancies and how your ATS supports real-time updates. If your ATS offers reliable webhooks, near-instant updates are achievable and preferable, since a vacancy closed in the morning should not still be showing as open on the website in the afternoon. Where webhooks are not available or are unreliable, a polling schedule of every few minutes is usually a reasonable balance between freshness and not overloading the ATS API with requests. In our builds we typically combine both: webhooks for immediate updates plus a scheduled reconciliation job that catches anything missed, which gives you both speed and a safety net without depending entirely on one mechanism working perfectly all the time.

What happens to our website if the ATS goes down?

This depends entirely on how the integration was built. If your website fetches vacancy data live on every page request with no caching layer, an ATS outage will show as broken or empty listings on your public site, which is a serious and entirely avoidable problem for a business that relies on those listings to generate applications. We build a caching layer that stores the last known good vacancy dataset and serves from it during an ATS outage, with a defined staleness tolerance so visitors always see functioning content even if it is a few minutes or hours old rather than completely current. This is a standard resilience pattern in software engineering that is still surprisingly rare in recruitment website builds, largely because it requires deliberate architectural planning rather than a simple live API call.

Why do our job pages load so much slower than the rest of our site?

Job pages typically combine several performance-hurting factors that other pages on your site do not have: a live or near-live data fetch from an external ATS, client-side filtering and search widgets, third-party application form embeds, and often a job board plugin retrofitted onto a general-purpose CMS template. Each of these adds latency, JavaScript execution time or layout instability on top of what a static content page needs to handle. Fixing this requires treating job pages as their own performance budget rather than assuming the same template optimisations that work for your homepage will carry over. Deferring non-essential scripts, caching listing data at the edge, and reserving layout space for asynchronously loaded elements typically account for the largest improvements we see in recruitment website performance audits.

How does JobPosting structured data actually help us commercially?

JobPosting schema, when valid, makes a vacancy eligible to appear in Google's dedicated job search features, which sit in a distinct part of the results page above standard organic listings and tend to attract different click behaviour from candidates actively searching for roles. Vacancies without valid structured data are simply not eligible for that visibility regardless of how well the underlying page is written or optimised. The commercial value is straightforward: more qualified candidate traffic reaching vacancy pages without additional job board spend. The technical challenge is maintaining validity over time, since required fields, salary formatting and date requirements are strict, and a data model that changes as your ATS or website evolves can silently break compliance unless it is actively monitored.

Should every vacancy on our site be indexed by Google?

No, and treating indexation as an automatic default for every ATS-generated URL is one of the more common technical SEO problems we find in recruitment website audits. Near-duplicate vacancies across multiple taxonomy pages, extremely thin listings with little client-provided description, and expired roles left live all contribute to a lower-quality indexation profile that can drag down how search engines perceive the whole domain, even though no individual page is doing anything wrong. Deliberate indexation control, using canonical tags, noindex rules for thin or expired content, and segmented sitemaps that prioritise fresh vacancies, produces a smaller but higher-quality indexed footprint that tends to perform better in aggregate than an unmanaged approach that indexes everything by default.

What should happen to a job page once the vacancy is filled?

A hard 404 is the weakest option, since it discards any ranking signal the page had accumulated and frustrates candidates arriving from saved job alerts or external job board links. A blank expired-vacancy page with no further content is also weak, since it gets indexed as thin, low-value content. Our default approach is a redirect to a closely related live vacancy or to the relevant sector or location listing page, which preserves the visit and gives the candidate somewhere useful to go, combined with updating the JobPosting schema to mark the role as no longer valid so it stops surfacing in job-specific search features. This approach protects both the candidate experience and the site's broader SEO health.

How do you handle inconsistent or messy data coming from our ATS?

We build a normalised job model that every ATS payload is mapped into before it reaches the website's templates, rather than building directly against the ATS's raw field structure. This means salary formats, location naming and sector categorisation are standardised regardless of how inconsistently they were entered at source, and validation rules flag incomplete or malformed entries, such as a missing salary or an unrecognised location, so they can be corrected rather than published as broken content. This layer also insulates the rest of the website from ATS quirks, meaning that if you ever migrate to a different ATS in future, the front end and structured data do not need to be rebuilt, only the mapping layer needs to be updated.

How long does a recruitment website development project typically take?

It depends heavily on ATS integration complexity, vacancy volume, and how much of the front-end design is being built fresh versus adapted from an existing brand. A straightforward rebuild with a well-documented ATS API and a moderate vacancy count is a meaningfully smaller project than one involving multiple ATS platforms, multi-brand structures, or an ATS with a poorly documented or unreliable API that requires more discovery and defensive engineering. We scope timelines after the technical discovery phase specifically because the ATS integration is usually the variable that most affects the schedule, far more than the visual design work.

Do you migrate our existing job data and URLs, or start fresh?

Wherever a vacancy or historical job page has search visibility worth preserving, we map old URLs to new ones with appropriate redirects rather than starting fresh and losing that equity. For live vacancies, data migrates through the same normalised job model used for ongoing ATS syncing, so there is no separate one-off migration script that then falls out of sync. For historical or expired vacancy pages that were previously indexed, we make a deliberate decision per site about whether to preserve them as a lightweight archive with appropriate schema, redirect them to relevant current content, or let them drop out of the index, based on how much organic value they are actually carrying.

Can you work with our existing ATS, or do we need to change systems?

In the large majority of cases we build against your existing ATS. Most established ATS platforms used by UK and US recruitment agencies expose an API or webhook capability that we can integrate with, even if the documentation is patchy or the implementation needs some defensive engineering around edge cases. We would only recommend considering a different ATS if the current one has no viable integration path at all, which is rare, or if the agency is already reconsidering its ATS for reasons unrelated to the website. Our technical discovery phase includes an assessment of your specific ATS's API capabilities before we finalise the architecture, so any constraints are identified and planned for early rather than discovered mid-build.

Recruitment website development