SC-200Chapter 15 of 101Objective 2.2

Sentinel Watchlists

This chapter covers Microsoft Sentinel watchlists, a critical feature for enriching alerts and speeding up threat hunting queries. On the SC-200 exam, watchlists appear in about 5-8% of questions, often in the context of custom analytics rules and hunting queries. Understanding how to create, manage, and query watchlists is essential for passing Domain 2 (Sentinel) and for real-world security operations. We will dive deep into the internal mechanics, configuration, and exam-specific traps.

25 min read
Intermediate
Updated May 31, 2026

Sentinel Watchlists: The VIP Guest List

Imagine you are a security guard at a corporate headquarters. You have a printed 'VIP guest list' that contains the names and badge numbers of executives, contractors, and known visitors who are allowed special access. When someone approaches the entrance, you check their ID against this list. If their name is on the list, you grant them expedited entry or notify the executive assistant. If someone is not on the list, they follow the standard visitor procedure. The watchlist is like that printed list: you predefine a set of entities (IP addresses, account names, hostnames) that you want to flag or correlate during log analysis. In Microsoft Sentinel, a watchlist is a CSV file or a set of key-value pairs stored in the workspace. When a query runs, it can perform a lookup against the watchlist using the _GetWatchlist function or KQL's lookup operator. This is much faster than writing a complex join against a Log Analytics table, because the watchlist is cached and indexed. Just as the guard's list is a static reference that speeds up decision-making, Sentinel watchlists accelerate threat detection by allowing you to reference known bad IPs, sensitive accounts, or asset inventories without querying external databases every time. The mechanism is simple: you upload or create a watchlist via the portal, API, or PowerShell, and then any KQL query can join against it using the watchlist alias. The watchlist is stored as a table in the workspace (under the Watchlist table), but it is optimized for lookups. When you use _GetWatchlist('myList'), Sentinel retrieves the entire watchlist and caches it for the query duration. This is analogous to the guard memorizing the VIP list for the shift—subsequent checks are instant.

How It Actually Works

What is a Sentinel Watchlist?

A watchlist in Microsoft Sentinel is a collection of data items (such as IP addresses, file hashes, or user accounts) that you can use to enrich logs, filter events, or correlate with threat intelligence. Watchlists are stored as a dedicated table in your Log Analytics workspace (Watchlist), but they are optimized for fast lookups. They are essentially key-value pairs with a schema you define. You can create up to 30 watchlists per workspace (soft limit), each with a maximum of 10 MB of data (or 10,000 rows, whichever is smaller).

Why Watchlists Exist

Security analysts often need to reference static or semi-static data sets: lists of known malicious IPs, sensitive admin accounts, asset inventories, or employee IDs. Without watchlists, you would have to either hardcode values in queries (which is inflexible) or join against external tables (which is slow and costly). Watchlists provide a lightweight, cached, and easy-to-manage solution. They are designed for scenarios where the data changes infrequently but needs to be referenced frequently in queries.

Internal Mechanism

When you create a watchlist, Sentinel stores the data in a hidden table in the Log Analytics workspace. The table name follows the pattern Watchlist_<GUID> but you access it via an alias you define (e.g., MyIPList). The data is stored as rows with columns: SearchKey (the key you search on), SearchValue (the value), and additional custom columns. The SearchKey is the column you will use for lookup operations. Internally, Sentinel uses Azure Data Explorer's storage engine to host this data. When a query uses the _GetWatchlist('alias') function, the entire watchlist is loaded into memory for the duration of the query. This is why watchlists are limited in size—they are not meant for large datasets (use Threat Intelligence for that).

Key Components

Watchlist alias: A friendly name used in KQL queries (e.g., MyIPList). Must be unique per workspace.

SearchKey: The column designated for lookups. This is the column that KQL's lookup operator uses by default.

Items: The rows of data. Each item is a JSON object with key-value pairs.

Source: Watchlists can be created from a local CSV file, Azure Storage blob, or manually via the portal/API.

Status: Watchlists can be Enabled or Disabled. Disabled watchlists are not loaded into queries.

Default duration: Watchlists are cached for the duration of the query. There is no TTL; they persist until deleted.

Configuration and Verification

To create a watchlist via the portal: 1. Navigate to Microsoft Sentinel > Your workspace > Configuration > Watchlist. 2. Click "Add new". 3. Provide a name, alias, and description. 4. Upload a CSV file (first row must be column headers). 5. Set the SearchKey column (the column used for lookups). 6. Optionally set a validity period (start/end date) for the watchlist items. 7. Click "Add".

To create via PowerShell:

$watchlistProps = @{
    Name = 'MyIPList'
    Alias = 'MyIPList'
    Description = 'List of known bad IPs'
    DisplayName = 'Bad IPs'
    Provider = 'Custom'
    Source = 'Local file'
    RawContent = (Get-Content -Path 'C:\badIPs.csv' -Raw)
    ItemsSearchKey = 'IPAddress'
}
Set-AzSentinelWatchlist -ResourceGroupName 'rg-sentinel' -WorkspaceName 'sentinel-workspace' -Watchlist $watchlistProps

To verify:

_GetWatchlist('MyIPList')
| take 10

How It Interacts with Related Technologies

Analytics Rules: Watchlists can be referenced in custom analytics rules to generate alerts when an event matches a watchlist entry. For example, "Alert when a login from IP in BadIPs watchlist".

Hunting Queries: Watchlists are commonly used in hunting queries to enrich results or filter out noise.

Playbooks: Watchlists can be queried by Azure Logic Apps via the Sentinel connector, enabling automated responses based on watchlist matches.

Threat Intelligence: Unlike Threat Intelligence, watchlists are not automatically updated from external feeds. They are manually managed.

Performance Considerations

Watchlists are loaded entirely into memory for each query that uses _GetWatchlist. Therefore, large watchlists (near the 10 MB limit) can cause query performance degradation. For large datasets, consider using Threat Intelligence or custom Log Analytics tables with appropriate indexing. Also, watchlists are not meant for real-time updates; they are eventually consistent within a few seconds after creation/update.

Default Values and Limits

Maximum watchlists per workspace: 30 (soft limit, can be increased by support request)

Maximum size per watchlist: 10 MB

Maximum rows per watchlist: 10,000

Maximum columns per watchlist: 20

SearchKey column: Must be a string type

Watchlist data is stored in the workspace's Log Analytics store; you are billed for ingestion and retention.

Exam-Relevant Details

The _GetWatchlist function returns the entire watchlist as a table. You can then use KQL operators like where, lookup, or join.

The lookup operator is optimized for watchlists: T | lookup kind=leftouter ( _GetWatchlist('MyList') ) on $left.IP == $right.SearchKey.

Watchlists can have a validity period (start and end date). If the current time is outside the range, the watchlist item is not returned by _GetWatchlist.

You can update a watchlist by uploading a new version; the old data is replaced.

Watchlists are visible in the Watchlist table, but you should not query that table directly—use _GetWatchlist.

Step-by-Step Mechanism of a Watchlist Lookup

1.

User uploads CSV with columns: IPAddress, Description, Confidence.

2.

Sentinel creates a hidden table Watchlist_<GUID> with columns: SearchKey (IPAddress), SearchValue (Description), Confidence, and metadata.

3.

When a query runs _GetWatchlist('MyIPList'), Sentinel retrieves all rows from that hidden table and returns them as a table.

4.

The query then uses lookup to match events: SecurityEvent | lookup _GetWatchlist('MyIPList') on $left.IpAddress == $right.SearchKey.

5.

For each event, if the IP matches a SearchKey, the corresponding row (Description, Confidence) is appended.

6.

The result is an enriched event that can be used for alerting or analysis.

Common Pitfalls

Using _GetWatchlist without specifying the alias: _GetWatchlist() returns all watchlists? No, it requires an alias.

Forgetting to set the SearchKey column: The lookup operator defaults to the SearchKey column; if not set, the lookup fails.

Assuming watchlists are real-time: They are not; there is a propagation delay of a few seconds.

Exceeding limits: Queries involving large watchlists may time out after 10 minutes.

Walk-Through

1

Plan Watchlist Schema and Data

Before creating a watchlist, define its purpose and structure. For example, a watchlist for known malicious IPs should have columns: IPAddress (SearchKey), Description, Confidence, and Source. The SearchKey column must be a string and will be used for lookups. Ensure the CSV file has headers that match the column names. The watchlist alias must be unique within the workspace. Plan the size: max 10 MB or 10,000 rows. If your list exceeds these limits, consider using Threat Intelligence or a custom table instead.

2

Create the Watchlist via Portal or PowerShell

In the Sentinel portal, go to Configuration > Watchlist > Add new. Enter a name (e.g., 'Malicious IPs'), alias (e.g., 'MaliciousIPs'), and optional description. Upload the CSV file. Select the SearchKey column (e.g., IPAddress). Optionally set a validity period (start/end dates). Click Add. Alternatively, use the `Set-AzSentinelWatchlist` PowerShell cmdlet. The watchlist is now stored in the workspace's hidden table. It may take a few seconds to appear in queries.

3

Verify Watchlist Creation

Run a simple KQL query to verify: `_GetWatchlist('MaliciousIPs') | take 10`. This should return the rows from the CSV. If it returns no results, check the alias spelling and ensure the watchlist is enabled. You can also check the Watchlist blade in the portal to see the status. If the watchlist has a validity period, ensure the current time falls within the range.

4

Use Watchlist in a KQL Query

Write a KQL query that references the watchlist. For example, to find sign-ins from malicious IPs: `SigninLogs | lookup kind=leftouter _GetWatchlist('MaliciousIPs') on $left.IPAddress == $right.SearchKey | where isnotempty(Description)`. The `lookup` operator enriches each sign-in event with the watchlist data if the IP matches. Without the `where` clause, you get all sign-ins with null for non-matches. You can also use `join` but `lookup` is more efficient.

5

Create an Analytics Rule Using Watchlist

To generate alerts automatically, create a custom analytics rule that queries the watchlist. In the Analytics blade, create a scheduled query rule. Use a query like: `SigninLogs | where IPAddress in (_GetWatchlist('MaliciousIPs') | project SearchKey)`. Set the frequency (e.g., 5 minutes) and alert threshold. This rule fires an incident whenever a sign-in from a watchlisted IP occurs. Configure the rule to map entities correctly (e.g., IPAddress, Account). Test the rule with sample data.

What This Looks Like on the Job

Enterprise Scenario 1: Blocking Known Malicious IPs

A large enterprise receives thousands of sign-in attempts daily. The SOC maintains a list of known malicious IPs from threat feeds and internal analysis. They create a Sentinel watchlist called 'MaliciousIPs' with columns: IPAddress, Source, and DateAdded. Every 5 minutes, a scheduled analytics rule queries SigninLogs and joins against this watchlist. When a match occurs, an incident is created with high severity. The watchlist is updated weekly by the threat intelligence team via a PowerShell script that downloads the latest CSV from a secure storage account. The watchlist currently has 5,000 entries, well within the 10,000 limit. Performance is acceptable; the query completes in under 30 seconds. One challenge: if the watchlist grows to 9,000 rows, the query may take longer. They plan to split into two watchlists or migrate to Threat Intelligence if needed.

Enterprise Scenario 2: Asset Inventory Enrichment

A company wants to enrich all security events with asset owner information. They have a CSV file mapping hostnames to owners and departments. They create a watchlist 'AssetOwners' with SearchKey=Hostname and columns: Owner, Department. In hunting queries, they use: SecurityEvent | lookup _GetWatchlist('AssetOwners') on $left.Computer == $right.SearchKey. This adds owner info to every event, making it easier to contact the right person during an incident. The watchlist is updated quarterly. Because the watchlist has only 2,000 rows, performance is excellent. They also use it in a fusion rule to correlate events from the same owner's machines.

Scenario 3: False Positive Suppression

A SOC uses a watchlist to suppress alerts for known good IPs (e.g., internal scanners, legitimate partners). They create a watchlist 'SafeIPs' and modify analytics rules to exclude those IPs: SigninLogs | where IPAddress !in (_GetWatchlist('SafeIPs') | project SearchKey). This reduces noise significantly. However, they must ensure the watchlist is kept current; stale entries can cause missed detections. They set a validity period so that entries older than 90 days are automatically excluded. Misconfiguration: initially they used !in with a subquery that returned multiple columns, causing errors. They fixed by projecting only SearchKey.

Performance Considerations

In production, watchlists are cached per query. If multiple queries run concurrently, each loads the watchlist separately. For high-frequency queries (e.g., every 1 minute), consider using a smaller watchlist or caching the results in a Log Analytics table. Also, watchlist data counts toward your workspace ingestion and retention costs. A 10 MB watchlist stored for 90 days incurs storage costs. Large watchlists may cause query throttling if the query consumes too much data. Use _GetWatchlist only when necessary; for very large datasets, prefer Threat Intelligence or custom tables with indexing.

How SC-200 Actually Tests This

What SC-200 Tests on Watchlists

The SC-200 exam covers watchlists under Domain 2.2: Configure and manage Microsoft Sentinel. Specifically, you need to know:

How to create and manage watchlists (portal, PowerShell, API).

How to reference watchlists in KQL queries using _GetWatchlist and lookup.

Use cases: enrichment, filtering, correlation, and alerting.

Limitations: size (10 MB, 10,000 rows, 30 per workspace), SearchKey requirement, and validity periods.

Differences between watchlists and Threat Intelligence.

Common Wrong Answers and Traps

1.

Watchlists are real-time: Candidates often think watchlists update instantly. Reality: there is a propagation delay of a few seconds. The exam may present a scenario where a watchlist is updated and immediately queried, and the answer choice that says "results appear instantly" is wrong.

2.

Watchlists support all data types: The SearchKey must be a string. If a candidate tries to use an integer column as SearchKey, it will fail. The exam may test this by showing a CSV with numeric IPs (e.g., 19216811) without dots.

3.

Watchlists can be used in fusion rules: Fusion rules use machine learning and cannot directly reference watchlists. Candidates may confuse fusion with scheduled rules. The correct answer is that scheduled analytics rules support watchlists, not fusion.

4.

`_GetWatchlist` returns a single value: It returns a table. Candidates may think it returns a scalar. The exam may ask which KQL function returns the watchlist as a table; answer: _GetWatchlist.

5.

Watchlists are automatically populated from threat intelligence feeds: They are not. Watchlists are manually managed. The exam may contrast with Threat Intelligence, which can be connected to external feeds.

Specific Numbers and Terms on the Exam

Maximum watchlist size: 10 MB or 10,000 rows (whichever is smaller).

Maximum watchlists per workspace: 30.

SearchKey column: must be string.

Function name: _GetWatchlist('alias').

KQL operator for efficient join: lookup.

Watchlist alias: must be unique per workspace.

Validity period: start and end date; items outside range are excluded.

Edge Cases and Exceptions

If a watchlist has a validity period and the current time is outside the range, _GetWatchlist returns an empty table. The query will not fail but will produce no matches.

If the watchlist alias does not exist, _GetWatchlist returns an error. Candidates should know to check the alias.

Watchlists can be disabled. A disabled watchlist returns an empty table when queried.

When using lookup, if the right side has duplicate SearchKey values, the left row gets multiple matches (cartesian product). The exam may test how to handle duplicates.

How to Eliminate Wrong Answers

If a question asks about real-time updates, eliminate any answer that says "immediately" or "real-time".

If a question involves large datasets (>10 MB), the correct answer will suggest Threat Intelligence or custom tables, not watchlists.

If a question mentions automatic updates from external feeds, watchlists are not the answer; Threat Intelligence is.

If a question asks about enriching events in a query, the correct answer will involve lookup or _GetWatchlist.

If a question asks about creating a watchlist via API, the correct cmdlet is Set-AzSentinelWatchlist (PowerShell) or REST API PUT.

Exam Tip

Memorize the limits: 10 MB, 10,000 rows, 30 watchlists, SearchKey string, _GetWatchlist function. Practice writing KQL queries with lookup and _GetWatchlist in the Sentinel demo environment.

Key Takeaways

Watchlists are stored as a hidden table in the Log Analytics workspace and accessed via `_GetWatchlist('alias')`.

The SearchKey column must be a string; it is used for lookup operations.

Maximum watchlist size: 10 MB or 10,000 rows (whichever is smaller).

Maximum watchlists per workspace: 30 (soft limit).

Watchlists have a propagation delay of a few seconds after creation/update.

Use the `lookup` KQL operator for efficient join against a watchlist.

Watchlists can have a validity period (start/end date); items outside the range are excluded.

Watchlists are not automatically updated from external feeds; they are manual.

For large datasets, use Threat Intelligence instead of watchlists.

Watchlists can be used in scheduled analytics rules, hunting queries, and playbooks.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Watchlists

Manually managed via CSV, portal, or API.

Limited to 10 MB or 10,000 rows per list.

Optimized for fast lookups in KQL queries using `_GetWatchlist`.

No automatic updates from external feeds.

Best for small, static reference data (e.g., known bad IPs, asset lists).

Threat Intelligence

Can be automatically populated from threat intelligence feeds (e.g., TAXII, AlienVault).

Virtually unlimited size (stored in ThreatIntelligenceIndicator table).

Queried using `ThreatIntelligenceIndicator` table or `where` clauses.

Supports automatic updates based on feed schedules.

Best for large, dynamic threat data (e.g., millions of indicators from multiple sources).

Watch Out for These

Mistake

Watchlists update in real time when modified.

Correct

Watchlists have a propagation delay of a few seconds after creation or update. They are eventually consistent, not real-time. Queries run immediately after an update may still see the old data.

Mistake

Watchlists can store any data type for the SearchKey column.

Correct

The SearchKey column must be a string. If you upload a CSV with a numeric column as SearchKey, Sentinel will convert it to string, but the lookup may fail if the event column is not also string. Best practice is to use string columns.

Mistake

You can have unlimited watchlists per workspace.

Correct

The soft limit is 30 watchlists per workspace. This can be increased by contacting support, but the default is 30. Exceeding this limit causes creation failures.

Mistake

Watchlists are automatically populated from threat intelligence feeds.

Correct

Watchlists are manually managed. You must upload data via CSV, PowerShell, or API. Threat Intelligence, on the other hand, can be connected to external feeds like VirusTotal or AlienVault for automatic updates.

Mistake

The `_GetWatchlist` function returns a single value (scalar).

Correct

`_GetWatchlist` returns a table with all rows and columns of the watchlist. To get a single column for use with `in` operator, you must project the SearchKey column.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

How do I create a watchlist in Microsoft Sentinel?

You can create a watchlist via the Azure portal: navigate to Microsoft Sentinel > Your workspace > Configuration > Watchlist > Add new. Provide a name, alias, and upload a CSV file. Set the SearchKey column (the column used for lookups). Optionally set a validity period. You can also use PowerShell with `Set-AzSentinelWatchlist` or the REST API. The watchlist will be available for queries within a few seconds.

What is the difference between a watchlist and a threat intelligence indicator in Sentinel?

Watchlists are manually managed, limited in size (10 MB, 10,000 rows), and stored in a hidden table accessed via `_GetWatchlist`. They are ideal for small, static reference data. Threat Intelligence indicators are automatically ingested from external feeds (e.g., TAXII), have no size limit, and are stored in the `ThreatIntelligenceIndicator` table. They are better for large, dynamic threat data. Both can be used in analytics rules, but watchlists are simpler for small custom lists.

Can I use a watchlist in a fusion rule?

No. Fusion rules use machine learning to correlate multiple alerts and cannot directly reference watchlists. Watchlists can only be used in scheduled analytics rules, hunting queries, and playbooks. If you need to incorporate watchlist data into a fusion rule, you must first create an analytics rule that generates alerts based on the watchlist, and then fusion can correlate those alerts.

How do I query a watchlist in KQL?

Use the `_GetWatchlist('alias')` function to retrieve the watchlist as a table. For example: `_GetWatchlist('MyIPList') | take 10`. To join with another table, use the `lookup` operator: `SigninLogs | lookup kind=leftouter _GetWatchlist('MyIPList') on $left.IPAddress == $right.SearchKey`. You can also use `where` with `in`: `SigninLogs | where IPAddress in (_GetWatchlist('MyIPList') | project SearchKey)`.

What happens if I exceed the watchlist size limit?

If you try to upload a CSV larger than 10 MB or with more than 10,000 rows, Sentinel will reject the upload. You must either reduce the size or split the data into multiple watchlists. For larger datasets, consider using Threat Intelligence or a custom Log Analytics table. If you need more than 30 watchlists, you can request a limit increase via Azure support.

Can I update a watchlist without deleting it?

Yes, you can upload a new version of the watchlist (same alias) to replace the existing data. The old data is overwritten. There is no append mode; you must upload the entire new dataset. You can also update individual items via the API, but the easiest way is to re-upload the CSV.

Are watchlists billed separately?

Watchlist data is stored in your Log Analytics workspace and counts toward your data ingestion and retention costs. There is no separate charge for the watchlist feature itself. However, querying watchlists consumes query resources (data scanned), which may affect your Log Analytics costs if you run many queries.

Terms Worth Knowing

Ready to put this to the test?

You've just covered Sentinel Watchlists — now see how well it sticks with free SC-200 practice questions. Full explanations included, no account needed.

Done with this chapter?