Deploying a Custom SharePoint Search Topology with PowerShell (End-to-End)

Post #1 in this series covered the design decisions behind a production-ready SPSE search topology — component placement, single vs. dual SSA, SQL sizing, and HA configuration. This post is about execution — running the four-script pipeline that takes a bare SPSE farm from no search to a fully provisioned, HA-ready Search Service Application with correctly sized crawl databases and an optimised component topology.

Topology deployment has a precise order of operations. Skipping steps or running them out of sequence produces failure modes that are hard to diagnose — a topology stuck in “Activating”, a crawl that never progresses, or an SSA that appears healthy but has no Admin component. This guide documents the correct sequence, the common failure modes, and how to recover cleanly.


The Four-Script Pipeline

The deployment uses four PowerShell scripts, each responsible for a distinct phase:

ScriptPhaseWhat It Does
New-SPSearchServiceApplication.ps11Creates the SSA, app pool, and initial single-server topology
Initialize-SPSearchArchitecture.ps12Creates crawl databases and content sources for Collaboration and My Sites
Optimize-SPSearchInfrastructure.ps13Redistributes components across dedicated index and app servers (large farm pattern)
Deploy-SPSearchInfrastructure.ps1OrchestratorCalls all phases in order with a single command

For most small to medium farms (4–6 servers), Phases 1 and 2 are sufficient, followed by applying the HA topology from Set-SPSearchCustomTopology.ps1 (Post #1). The orchestrator Deploy-SPSearchInfrastructure.ps1 is the production command — it accepts all parameters and runs phases 1 through 4 sequentially.

Note: Optimize-SPSearchInfrastructure.ps1 is covered in depth in Post #3. For a 4-server farm, Set-SPSearchCustomTopology.ps1 (Post #1) is the appropriate topology script. The orchestrator calls the simpler topology script for standard deployments.


Prerequisites Checklist

Complete every item in this checklist before running any script. Most deployment failures can be traced back to a missing prerequisite.

Index Directories

Create the index directory on every server that will host an Index component. The directory must be empty — a non-empty directory causes topology activation to fail silently.

D:\SearchIndex (or your chosen path)

Required permissions on each directory:

AccountPermission
<DOMAIN>\<SearchServiceAccount>Full Control
WSS_ADMIN_WPGFull Control
WSS_WPGRead

SQL Permissions

The Search service account needs dbcreator on the SQL instance to create crawl and link databases. If your DBA policy prohibits this, pre-create the databases manually and grant db_owner to the search service account on each one.

Managed Accounts

Register all three service accounts with Register-SPManagedAccount before running:

# Run once per account if not already registered
$cred = Get-Credential
Register-SPManagedAccount -Credential $cred

You need:

  • AppPoolAccount — runs the Search service application IIS application pool.
  • SearchServiceAccount — runs the Search Host Controller and related Windows services.
  • ContentAccessAccount (the Default Content Access Account) — the crawler uses this account to request content from WFEs.

MinRole

Servers that will host search components must be on the ApplicationWithSearch or Custom MinRole. Servers on WebFrontEnd, DistributedCache, or SingleServerFarm roles cannot host search components.

Verify roles in Central Admin → Servers in Farm, or via PowerShell:

Get-SPServer | Select Name, Role

Phase 1: Creating the Search Service Application

New-SPSearchServiceApplication.ps1 provisions the SSA on a single server first. The topology starts as a single-server deployment — all six components on APP-SERVER-1 — and is then redistributed in Phase 2 or by Set-SPSearchCustomTopology.ps1.

.\New-SPSearchServiceApplication.ps1 `
-ServerName "<APP-SERVER-1>" `
-SSAName "Search Service Application" `
-IndexLocation "D:\SearchIndex" `
-DatabaseName "SP_Search_SSA" `
-AppPoolAccount "<DOMAIN>\<AppPoolServiceAccount>" `
-SearchServiceAccount "<DOMAIN>\<SearchServiceAccount>" `
-ContentAccessAccount "<DOMAIN>\<SearchContentAccessAccount>"

What the script creates:

  1. Starts SPEnterpriseSearchServiceInstance and SPEnterpriseSearchQueryAndSiteSettingsServiceInstance on the target server.
  2. Creates or updates the IIS application pool with the App Pool managed account.
  3. Provisions the SSA with the search administration database on the Configuration Database’s SQL server.
  4. Creates the SSA proxy so the SSA is accessible to web applications.
  5. Builds an initial topology with all six components on the target server.
  6. Activates the topology and waits for the initial topology to become Inactive before removing it.
  7. Sets the Search service account and the Default Content Access Account from managed accounts — no passwords are passed as parameters.

Idempotency: If the SSA already exists, the script removes it (with -RemoveData), stops the service instances, and cleans up the index directory. Re-running the script after a failed first attempt is safe.

Phase 1 Validation

# Confirm the SSA exists
Get-SPEnterpriseSearchServiceApplication
# Confirm the proxy exists
Get-SPServiceApplicationProxy | Where-Object { $_.TypeName -like "*Search*" }
# Confirm all 6 components are Active
$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Active |
Get-SPEnterpriseSearchComponent | Select Name, ServerName, State

All six components should report State = Active on APP-SERVER-1.


Phase 2: Initialising the Search Architecture

Initialize-SPSearchArchitecture.ps1 creates additional crawl databases and maps content sources to specific databases. This is the step that enables parallel crawl processing and separates collaboration content crawl load from My Sites crawl load.

Why Run It Twice

The script accepts a -Target parameter (Collaboration or “My Sites”). You run it once per content type. This creates separate, named crawl databases for each type — preventing collaboration content crawl queue depth from affecting My Sites crawl queue depth.

# Create 2 crawl databases for Collaboration Sites
.\Initialize-SPSearchArchitecture.ps1 `
-Target Collaboration `
-SSAName "Search Service Application" `
-SQLServer "<YOUR-SQL-SERVER>\<INSTANCE>" `
-CrawlDBCount 2 `
-ContentSourceCount 2
# Create 2 crawl databases for My Sites
.\Initialize-SPSearchArchitecture.ps1 `
-Target "My Sites" `
-SSAName "Search Service Application" `
-SQLServer "<YOUR-SQL-SERVER>\<INSTANCE>" `
-CrawlDBCount 2 `
-ContentSourceCount 2

Choosing CrawlDBCount

A useful starting point: one crawl database per major content type or web application. Scale out by adding additional crawl databases when you observe sustained crawl queue backup during incremental crawl cycles. For large enterprise farms (80M+ items) where crawl queue depth becomes a bottleneck, see Post #3 for the extended sizing guidance.

The -ContentSourceCount parameter creates content source groups that each map to a specific crawl database. Match it to -CrawlDBCount so each content source has a dedicated crawl database.

Phase 2 Validation

$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
# Confirm crawl databases
Get-SPEnterpriseSearchCrawlDatabase -SearchApplication $ssa | Select Name, DatabaseServer
# Confirm content sources
Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $ssa | Select Name

You should see databases named Search_Crawl_DB_Collaboration_01, Search_Crawl_DB_Collaboration_02, Search_Crawl_DB_MySites_01, Search_Crawl_DB_MySites_02 (for a count of 2 per type).


Phase 3: Applying the HA Topology

For a 4-server farm, apply the HA topology using Set-SPSearchCustomTopology.ps1 (Post #1 scripts):

.\Set-SPSearchCustomTopology.ps1 `
-SSAName "Search Service Application" `
-SearchServers "<APP-SERVER-1>", "<APP-SERVER-2>"

For a large farm topology with dedicated index servers, use Optimize-SPSearchInfrastructure.ps1 (Post #3). See Post #3 for the full parameter walkthrough.


Running the Orchestrator

Deploy-SPSearchInfrastructure.ps1 calls all phases in sequence. This is the command you run in a maintenance window:

.\Deploy-SPSearchInfrastructure.ps1 `
-SQLServer "<YOUR-SQL-SERVER>\<INSTANCE>" `
-AppServers "<APP-SERVER-1>", "<APP-SERVER-2>" `
-SSAName "Search Service Application" `
-AppPoolAccount "<DOMAIN>\<AppPoolServiceAccount>" `
-SearchServiceAccount "<DOMAIN>\<SearchServiceAccount>" `
-ContentAccessAccount "<DOMAIN>\<SearchContentAccessAccount>" `
-CrawlDBCount 2 `
-MaxDownloadSizeMB 128 `
-ThreadsPerHost 16

The orchestrator outputs a phase-by-phase log. Each phase writes coloured progress to the console. Watch for yellow WARNING messages — they indicate idempotent conditions (e.g., “database already exists”) which are safe to ignore. Red ERROR messages require action before proceeding.


Common Failures and Their Fixes

Topology Stuck in “Activating”

Symptom: Set-SPEnterpriseSearchTopology returns, but the topology never reaches Active. The search topology page in Central Admin shows the new topology in “Activating” indefinitely.

Cause: The Index component cannot initialise. The most common reasons:

  1. The index directory does not exist on the target server.
  2. The index directory is not empty (leftover files from a previous failed attempt).
  3. The Search service account does not have Full Control on the directory.

Fix:

  1. Verify the directory exists and is empty.
  2. Verify permissions: icacls D:\SearchIndex
  3. Remove the stuck topology and re-run:
$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
Get-SPEnterpriseSearchTopology -SearchApplication $ssa |
Where-Object { $_.State -ne "Active" } |
Remove-SPEnterpriseSearchTopology -Confirm:$false

“Unable to Retrieve Topology Component Health State”

Symptom: Central Admin’s Search Topology page shows a health error, or Get-SPEnterpriseSearchComponent returns no Admin component.

Cause: The Admin component was not created on the first activation, or the topology was activated before all components were registered.

Fix: Re-run Set-SPSearchCustomTopology.ps1. The script explicitly removes all non-Active topologies and creates a fresh one — it does not clone the active topology, which avoids the duplicate component error.

Clean-Slate Recovery

If the SSA is in an unrecoverable state, perform a full clean-slate recovery:

# 1. Remove the SSA and all data
$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
Remove-SPServiceApplication $ssa -RemoveData -Confirm:$false
# 2. Remove orphaned proxy
$proxy = Get-SPServiceApplicationProxy | Where-Object { $_.Name -like "*Search*" }
if ($proxy) { Remove-SPServiceApplicationProxy $proxy -Confirm:$false }
# 3. Stop service instances on all search servers
Stop-SPEnterpriseSearchServiceInstance "<APP-SERVER-1>"
Stop-SPEnterpriseSearchServiceInstance "<APP-SERVER-2>"
# 4. Empty the index directories on all index servers
Remove-Item -Recurse -Force "D:\SearchIndex\*"
# 5. Re-run the deployment
.\Deploy-SPSearchInfrastructure.ps1 <params>

Note: Remove-SPServiceApplication -RemoveData drops the search administration, crawl, and link databases from SQL. If you need to preserve crawl history, back up the crawl databases before removing the SSA.


Post-Deployment Validation

After the orchestrator completes, run through this checklist:

$ssa = Get-SPEnterpriseSearchServiceApplication -Identity "Search Service Application"
# 1. All components Active
Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Active |
Get-SPEnterpriseSearchComponent | Select Name, ServerName, State
# 2. Correct number of crawl databases
Get-SPEnterpriseSearchCrawlDatabase -SearchApplication $ssa | Select Name
# 3. Start a Full Crawl
$source = Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $ssa | Select -First 1
$source.StartFullCrawl()
# Monitor crawl progress
Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $ssa |
Select Name, CrawlState, SuccessCount, ErrorCount

A healthy post-deployment state shows:

  • All six components Active on both App servers.
  • The correct number of crawl databases (4 for a 2+2 split, or your configured count).
  • A full crawl that progresses past 0 items within a few minutes of starting.

Summary

A correct SharePoint Search deployment follows four phases: SSA creation, crawl database initialisation, topology redistribution, and crawl impact configuration. Each phase has a defined output and validation step. Skipping the validation between phases is the primary source of hard-to-diagnose failures.

The Deploy-SPSearchInfrastructure.ps1 orchestrator in this post’s scripts/ folder automates the entire sequence. For farms that need the large farm topology with dedicated index servers, see Post #3 for how to integrate Optimize-SPSearchInfrastructure.ps1 into the deployment.

👉 SPSE Search Topology Starter Kit (Production-Ready PowerShell + PDF Runbooks)

👉 SPSE Search Config Backup Kit

👉 SPSE Search Deployment Kit for Large Farms

👉 SPSE Crawl Optimisation Kit 

👉 Complete SPSE Search Architecture Pack


Related Posts

  • Post #1: Designing the Right SharePoint Search Topology for Production SPSE Farms
  • Post #3: Scaling SharePoint Search for Large Enterprise Farms: Index Distribution and Crawl Isolation
  • Post #4: Controlling SharePoint Crawl Performance: Impact Rules and Crawl Rules
  • Post #5: Federated Search in SPSE: Searching Across Multiple Search Service Applications

Leave a Reply