Build a Bicycle Availability Monitor
Build a Fabric stream with raw bicycle events and one-minute street metrics.
Introduction
30 Second Summary
A bicycle station can shift from plenty of open docks to almost full in minutes. Operations teams need a quick street-level view before those individual updates become a service problem.
In this project, you will use Microsoft Fabric to build a bicycle availability monitor from simulated live events. An Eventstream will preserve each raw station record while Eventhouse stores one-minute street metrics for Kusto Query Language (KQL) analysis.
What You'll Build
You will watch a live bicycle monitor turn station updates into one-minute street summaries you can query.
By the end of this project, you'll have:
- A live bicycle feed where simulated station records keep arriving for inspection.
- Two queryable data products where RawBikeEvents preserves station records while BikeMinuteMetrics reveals minute-level street demand.
- An operational diagnosis that uses stream metrics to justify a low-throughput configuration.
- Secret Mission: Build a dock-pressure exception stream that routes matching stations into DockPressureAlerts.
Are there any prerequisites?
You need an active Microsoft Fabric trial workspace. Some Fabric experience helps with navigation.
Before We Start
Before any hands-on work, commit to retaining raw station events for audit and reprocessing. One-minute Street metrics give bicycle operations a more actionable view than individual station records.
Prepare Your Workspace and Eventhouse
The bicycle monitor needs a capacity-backed home before events begin moving. Your existing trial workspace supplies that capacity.
Microsoft Fabric also checks whether your workspace role can create items. This permission must be in place before the project resources can exist.
The first resource is an Eventhouse with a same-named KQL database. Together they give the future stream a real-time analytical destination.
In this step, get ready to:
- Verify your trial workspace can create Fabric items.
- Create the DP700BikeOps Eventhouse.
- Confirm the same-named DP700BikeOps KQL database.
Verify item-creation access
Your Fabric trial supports Real-Time Analytics. The New item experience provides a quick permission check without leaving a temporary resource behind.
- Sign in to Microsoft Fabric with the account linked to your active trial.
- Open the confirmed trial workspace from earlier.
- Select + New item in the workspace toolbar.
You should see the New item experience with a searchable list of Fabric items. That is the access hurdle cleared: this workspace can create the resources your monitor needs.
Blocked from creating items?
Workspace permissions determine whether you can create Fabric items. The workspace owner can update your role.
- Ask the workspace owner to grant the Contributor role or a higher role.
- Return to the same workspace after your access changes.
Help me diagnose my Microsoft Fabric workspace permissions.
Create the DP700BikeOps Eventhouse
An Eventhouse stores streaming data for real-time KQL analysis. Creating one also creates its child KQL database with the same name.
Why Eventhouse for this project?
Eventhouse supports real-time KQL analysis. This matches the monitor's need to query arriving station data.
A Lakehouse supports data warehousing scenarios. Eventhouse gives this project the primary query store its live operational checks need.
- Return to the New item experience from the permission check.
- Enter Eventhouse in the search field.
- Select Eventhouse from the search results.
- Name the Eventhouse DP700BikeOps.
- Submit the form to create the Eventhouse.
- Wait for provisioning to complete.
Fabric provisions the Eventhouse together with its child KQL database. A brief loading state is expected while both items are created.
Eventhouse not provisioning?
- Confirm the selected workspace still uses your active trial capacity.
- Confirm the permission check still opens the New item experience.
Help me troubleshoot Eventhouse provisioning in Microsoft Fabric.
Confirm both DP700BikeOps items
The System overview connects the Eventhouse to its child KQL database. Matching names confirm Fabric created the expected analytical destination.
Before you select Get started, predict whether Fabric will show one item or two.
- Select Get started for DP700BikeOps.
- Confirm System overview opens for the DP700BikeOps Eventhouse.
- Confirm the child KQL database is named DP700BikeOps.
You should see the Eventhouse System overview for DP700BikeOps. Its child KQL database should also be named DP700BikeOps.
That setup hurdle is cleared: your bicycle monitor now has a real-time analytical destination.
Your workspace is ready for streaming work. Next, you will bring simulated bicycle records to life in a Microsoft Fabric Eventstream.
Create the Live Bicycle Stream
Your DP700BikeOps Eventhouse is ready to receive real-time data. The next goal is to create a stream you can see moving before storage choices add complexity.
A Microsoft Fabric Eventstream carries events from a source through a live pipeline. The Bicycle rentals sample gives you continuously arriving station records for an early working baseline.
In this step, get ready to:
- Choose the Bicycle rentals sample as the live input.
- Create DP700BikeStream with the source name BikeSource.
- Verify continuously arriving Bicycle records in Live view.
Add the Bicycle rentals sample
The Bicycle rentals sample generates simulated station events inside Fabric. This gives you a repeatable stream without an external data source.
- Select Real-Time in the Microsoft Fabric navigation.
- Select Add data.
- Choose the Bicycle rentals sample tile.
You'll see the connection flow for the Bicycle rentals sample.
Can't find the Bicycle rentals tile?
- Confirm that you selected Real-Time before choosing Add data.
- Confirm that the current workspace is the trial workspace you verified earlier.
- Still stuck? Help me find the Bicycle rentals sample in Microsoft Fabric.
Name and connect the Eventstream
Fabric keeps the source node separate from the Eventstream item. Distinct names make each part easy to identify when you add more paths later.
- Enter BikeSource in Source name.
- Rename the Eventstream to DP700BikeStream.
- Confirm that the review shows BikeSource as the source name.
- Confirm that the review shows DP700BikeStream as the Eventstream name.
- Complete Review + connect to create the Eventstream.
That's the source connected. DP700BikeStream now receives its live input from BikeSource.
Eventstream not created?
- Confirm that neither required name is blank in the connection flow.
- Confirm that you are still using the workspace where item-creation access was verified.
- Still stuck? Help me create the Bicycle sample Eventstream.
Inspect live Bicycle records
Live view exposes events before any Eventhouse destination or transformation exists. The preview becomes your baseline for the unprocessed event shape.
- Select Live view inside DP700BikeStream.
- Select BikeSource on the Eventstream canvas.
Before you inspect the preview, which station details do you expect each raw event to carry?
- Watch the event preview until several records arrive.
You'll see Bicycle records update continuously. Each record includes fields such as BikepointID, Street, No_Bikes, and No_Empty_Docks.
What can the raw event shape answer?
A single event identifies a bicycle station. It also shows the street plus the sampled bicycle and empty-dock counts.
The raw shape does not combine events across time. A one-minute street metric needs a time window.
Live preview not updating?
- Confirm that Live view is selected.
- Confirm that BikeSource is visible on the Eventstream canvas.
- Refresh the Fabric page if the preview remains still.
- Still stuck? Help me restore the live Bicycle event preview.
Your live baseline is working. Next, you'll route the unprocessed events into Eventhouse. You'll then test whether raw rows meet the minute-level requirement.
Ingest Raw Bicycle Events
Your live Microsoft Fabric Eventstream, DP700BikeStream, already shows Bicycle records arriving from BikeSource. The next question is whether those events can land unchanged in the DP700BikeOps Eventhouse.
Direct ingestion sends source events to a KQL database without event processing. You will prove that transport path before judging its stored shape against the one-minute street requirement.
In this step, get ready to:
- Configure RawDestination for Direct ingestion into DP700BikeOps.
- Create RawBikeEvents with JSON input.
- Inspect the stored rows against the one-minute street requirement.
Configure the direct-ingestion destination
A destination connects the live source to its analytical store. This destination keeps each Bicycle event in its incoming shape.
- Return to DP700BikeStream from earlier.
- Select Edit to switch from Live view to the eventstream canvas.
- Add an Eventhouse destination from the default stream.
The destination settings now define where the unchanged events travel.
- Enter RawDestination in the name field.
- Select Direct ingestion as the ingestion mode.
- Select DP700BikeOps as the Eventhouse.
The destination configuration should now show RawDestination pointing to DP700BikeOps through Direct ingestion.
- Select Connect if RawDestination displays that action.
- Select Save in the editor toolbar.
The eventstream canvas now includes RawDestination as the raw route from the default stream.
Why Use Direct Ingestion?
Direct ingestion sends events to Eventhouse without applying Eventstream operations. This preserves the source fields for detailed investigation.
Fabric does not let you edit the ingestion mode after adding the destination. Keeping RawDestination dedicated to raw transport protects this queryable event history.
Create the raw table
The destination defines where events go. The ingestion setup creates the table that stores those events inside the same-named database.
- Select Publish in the eventstream editor.
- Return to Live view after publishing finishes.
The published destination now exposes its ingestion configuration in Live view.
- Select Configure on RawDestination.
- Select New table in the Eventhouse ingestion setup.
- Enter RawBikeEvents as the table name.
- Select JSON as the input format.
- Inspect the data preview to confirm that fields such as BikepointID, Street, No_Bikes, plus No_Empty_Docks are present.
- Select Finish to complete the ingestion setup.
Good progress. BikeSource now feeds the new RawBikeEvents table through RawDestination.
Raw Table Setup Not Completing?
- Return to Edit mode if Configure is unavailable. Confirm that RawDestination was saved before publishing.
- Confirm that you selected the trial workspace containing the DP700BikeOps Eventhouse if it is missing from the destination setup.
- Still stuck? Help me troubleshoot the RawDestination ingestion setup in Microsoft Fabric.
Inspect the raw records
Successful ingestion proves that events reached storage. Querying the table tests whether their current shape answers the operations requirement.
- Return to the DP700BikeOps Eventhouse from earlier.
- Select the same-named DP700BikeOps KQL database.
- Select the RawBikeEvents table.
- Select Query table.
- Predict whether the query will show individual station events or one row per street per minute.
- Select Show any 100 records to run the table query.
You should see multiple unaggregated Bicycle records. Each row contains source fields such as BikepointID plus Street instead of one metric row per street and minute.
No Rows in RawBikeEvents?
- Confirm that BikeSource still shows incoming events in DP700BikeStream Live view.
- Return to RawDestination if the table is unavailable. Confirm that its ingestion setup finished.
- Still stuck? Help me find missing Bicycle records in RawBikeEvents.
That shortfall is intentional. You have proven that the raw transport works while exposing the gap between individual events and a time-based operational metric.
Why Do the Raw Rows Fall Short?
Each row preserves one source event. This shape supports detailed investigation of individual bicycle stations.
The operations requirement needs events summarized by Street within one-minute windows. Raw transport alone does not create that summarized view.
Changing RawDestination would remove the dedicated raw path. Its ingestion mode is also fixed after the destination is added.
Your raw ingestion path is proven. Next, you will turn the row-level stream into the operational view the scenario needs.
Build One-Minute Street Metrics
Your raw path has already proved that the Microsoft Fabric Eventstream delivers bicycle records to Eventhouse. Those records still cannot answer how many bicycles each street reported during each minute.
This step adds a tumbling window that turns the live flow into one-minute street metrics. The existing raw branch stays intact for audit and reprocessing.
In this step, get ready to:
- Configure a one-minute tumbling aggregation by Street.
- Route the grouped output into BikeMinuteMetrics.
- Publish the two-path Eventstream.
Add the one-minute transformation
A tumbling window divides the stream into fixed time intervals. Each completed minute produces a separate aggregate for every Street value seen during that interval.
- Switch back to DP700BikeStream in Edit mode.
- Select the default unprocessed stream.
You should see the actions available for the live stream from BikeSource.
- Add a Group by operation from the default stream.
The canvas should now show a separate Group by branch beside the existing raw path.
- Set the aggregation function to SUM.
- Select No_Bikes as the aggregation field.
The operation summary should now show that bicycle availability values are being summed.
- Select Street as the grouping field.
- Select Tumbling as the window type.
The operation now groups each window into separate results for the streets represented in that minute.
- Set Duration to 1 Minute.
Your Group by configuration should now show SUM over No_Bikes. It should also show grouping by Street within a one-minute tumbling window.
Why Use a Tumbling Window?
A tumbling window places each event into one fixed time bucket. Every completed minute produces a distinct result for each street.
This cadence gives bicycle operations a consistent minute-by-minute view of availability across active streets.
Route aggregates into Eventhouse
A second destination keeps the aggregate rows separate from the raw station events. Event processing before ingestion accepts output that has already passed through an Eventstream operation.
Fabric opens an ingestion setup while you connect this destination. You will create the target table during that setup.
- Add an Eventhouse destination from the Group by output.
- Enter MinuteMetricsDestination as the destination name.
The new destination should appear on the grouped branch of the canvas.
- Select Event processing before ingestion as the ingestion mode.
- Select DP700BikeOps as the Eventhouse.
The destination summary should now pair the processing ingestion mode with your existing Eventhouse.
- Select New table.
- Enter BikeMinuteMetrics as the table name.
The ingestion setup should now identify BikeMinuteMetrics as the destination table.
- Select JSON as the input format.
- Complete the ingestion setup.
You should see MinuteMetricsDestination connected to the Group by output.
Why Keep Both Destinations?
This fan-out design sends the same live stream down two independent paths. RawDestination preserves station-level events for audit or reprocessing.
MinuteMetricsDestination provides the smaller street-level view used for operations. Multiple Eventstream destinations can receive data without interfering with one another.
Preview and publish the stream
The preview checks the transformation before publishing. The first aggregate needs a full one-minute window to close, so a short pause is expected.
Before you inspect the preview, how many rows do you expect one active street to contribute for each completed minute?
- Select the Group by operation.
- Inspect its preview.
You should see one-minute output grouped by Street. The preview should contain aggregated values from No_Bikes.
- Select Save.
- Select Publish.
The published canvas should show RawDestination on the unprocessed path. It should show MinuteMetricsDestination after the Group by operation.
Before you inspect the table, do you expect station-level events or minute-level Street rows?
- Return to DP700BikeOps from earlier.
- Select BikeMinuteMetrics in the KQL database.
You should see the new table listed beside RawBikeEvents.
- Select Query table.
- Select Show any 100 records.
You should see incoming rows grouped by Street for completed one-minute windows. These rows provide the minute-level view that was missing from RawBikeEvents.
- Return to DP700BikeStream in Live view.
- Confirm that RawDestination remains on the unprocessed branch.
- Confirm that MinuteMetricsDestination remains on the grouped branch.
You now have the key streaming pattern working. Raw records remain available while minute-level street metrics arrive beside them.
No Aggregate Rows Yet?
- Allow one full minute for the current tumbling window to close.
- Refresh BikeMinuteMetrics after the window closes.
- Confirm that BikeSource is active in DP700BikeStream.
- Still stuck? Help me troubleshoot missing rows in BikeMinuteMetrics.
Your raw and aggregate paths are now working side by side. Next, you will validate the output with Kusto Query Language (KQL) before diagnosing the stream's runtime health.
Validate and Tune the Stream
Your published Microsoft Fabric Eventstream now preserves raw bicycle events in RawBikeEvents. A parallel path writes one-minute street aggregates to BikeMinuteMetrics.
A running stream still needs proof that its output is correct. It also needs operational evidence that the workload fits its capacity.
In this step, get ready to:
- Prove that BikeMinuteMetrics contains multiple windows.
- Diagnose the processing destination through its operational evidence.
- Right-size the Eventstream for the low-volume trial workload.
Validate the aggregate with KQL
The BikeMinuteMetrics table in your Microsoft Fabric Eventhouse receives one row for each street-level window. Kusto Query Language (KQL) can count those rows by street to prove that the windowed path keeps producing output.
A WindowsObserved value above 1 proves that the stream has produced multiple windows for that street.
- Create DP700BikeValidation.kql in the DP700BikeOps query editor with this query:
BikeMinuteMetrics
| summarize WindowsObserved = count() by Street
| top 5 by WindowsObserved desc
What does this query prove?
- BikeMinuteMetrics selects the table produced by the one-minute processing path.
- summarize WindowsObserved = count() counts the aggregate rows within each street group.
- Street keeps the result grouped by the field used in the Eventstream transformation.
- top 5 by WindowsObserved desc keeps up to five streets with the highest observed window counts.
- Save DP700BikeValidation.kql so the validation remains available.
Before you run the query, do you expect each active street to have one row or multiple rows?
- Run the saved DP700BikeValidation.kql query.
You should see up to five Street rows. Active streets should have a WindowsObserved value above 1.
That is the aggregate path proven: your table contains output from multiple one-minute windows.
No rows or only one window?
- Confirm that DP700BikeStream remains published.
- Confirm that MinuteMetricsDestination still points to BikeMinuteMetrics.
- Wait through another one-minute window before running the query again.
- Ask for help with the validation query by selecting Help me troubleshoot missing BikeMinuteMetrics results.
✔️ Awesome, I've got everything!
Your saved query matches the validation artifact for this project.
ⓧ I'd like to double check the full code
BikeMinuteMetrics
| summarize WindowsObserved = count() by Street
| top 5 by WindowsObserved desc
Inspect Eventstream operations
Operational metrics show whether events are entering the processing destination. They also reveal pressure or failures inside that path.
Runtime logs provide the detailed evidence behind those signals. Refreshing them gives you the latest view of warnings or errors.
- Return to DP700BikeStream in the trial workspace.
- Select MinuteMetricsDestination in the Eventstream editor.
- Open Data insights.
- Inspect Input events to confirm that its chart contains data.
- Inspect Output events to confirm that its chart contains data.
- Check Backlogged input events for queued work.
- Check Runtime errors for processing failures.
- Check Data conversion errors for conversion failures.
That is the operational path confirmed: both event-flow charts contain data.
How do these metrics fit together?
- Backlogged input events measures work waiting for processing.
- Runtime errors records failures while the destination processes events.
- Data conversion errors identifies events that could not be converted for the destination.
- Watermark delay shows how far event-time progress trails behind processing.
- Inspect Watermark delay for processing delay.
- Open Runtime logs for MinuteMetricsDestination.
- Refresh the runtime log view.
- Review the current logs for warnings.
- Review the current logs for errors.
The refreshed log view now shows whether current warnings or errors are present.
Charts still look empty?
The one-minute window can make a healthy chart look quiet briefly.
- Confirm that DP700BikeStream is published.
- Wait for another one-minute window before refreshing Data insights.
- Refresh Runtime logs after new output reaches the destination.
- Ask for help by selecting Help me diagnose empty Eventstream metrics or runtime logs.
Tune throughput for the trial workload
Capacity tuning should follow evidence from the running stream. The Low setting covers Event throughput below 10 MB/s.
The bicycle sample produces a low-volume trial workload. One-day retention matches the short operational window used in this project.
- Select Deactivate All in the DP700BikeStream editor.
- Wait for the supported nodes to show an inactive state.
The supported nodes now show as inactive. RawDestination can remain unpaused because Direct ingestion does not support pause.
- Open Settings.
- Set Event throughput to Low.
- Confirm that retention remains one day.
- Select Activate All.
The supported nodes return to an active state. New sample events can flow through both paths again.
Why does Low fit?
- Low supports Event throughput below 10 MB/s.
- Rising Backlogged input events indicates processing pressure.
- Rising Watermark delay indicates delayed event-time progress.
- Clear Data conversion errors points away from mapping problems.
- Together those signals make Event throughput the first setting to investigate.
Before the final check, do you expect BikeMinuteMetrics activity to resume after reactivation?
- Return to the saved DP700BikeValidation.kql query in DP700BikeOps.
- Run the saved query again.
The query returns up to five Street rows. Active streets show multiple observed windows.
- Return to DP700BikeStream.
- Select MinuteMetricsDestination.
- Open Data insights.
- Inspect the Input events chart for data.
- Inspect the Output events chart for data.
The Input events chart contains data. The Output events chart also contains data.
Strong finish: your streaming solution is validated against live data. Its throughput now matches the low-volume trial workload.
Secret mission
Build a Dock-Pressure Exception Stream
Dock pressure can disappear inside a stream of routine station records. This mission adds a filtered exception route that sends only matching records to DockPressureAlerts for focused operational review.
Clean Up Your Resources
Clean Up Your Resources
Choose whether to keep the bicycle monitor running, pause its supported nodes for later practice, or delete the project resources entirely. The project has no direct charge on your existing trial, but active streaming continues to use trial capacity.
Cost warning
Your existing Microsoft Fabric trial keeps this project at $0. An active DP700BikeStream still consumes trial capacity.
Trial content is time-bound. Anything you want to preserve needs an external copy before the trial expires.
Resources you used:
- The DP700BikeStream Eventstream.
- The DP700BikeOps Eventhouse.
- The DP700BikeOps KQL database.
- The RawBikeEvents table.
- The BikeMinuteMetrics table.
- The DockPressureAlerts table.
- The DP700BikeValidation.kql query.
Keep everything running
No action is needed. Choose this option if you want to continue practising KQL queries or monitoring the live bicycle pipeline.
- Keep DP700BikeStream published.
- Leave Event throughput set to Low.
- Leave the retention setting at one day.
- Use DP700BikeValidation.kql to continue checking the street-level windows in BikeMinuteMetrics.
BikeSource continues feeding the raw path and the one-minute aggregate path. The dock-pressure branch continues routing matching events into DockPressureAlerts.
Pause - I'll come back to this later
Pausing stops new sample flow while preserving the Eventstream and Eventhouse for later practice. Your tables and saved query remain available.
- Return to DP700BikeStream in the trial workspace.
- Select Deactivate All from the Eventstream menu bar.
- Confirm that BikeSource shows a deactivated state.
- Select Activate All when you return to the project.
New sample events stop reaching both destinations while BikeSource is deactivated. RawDestination does not support pause directly, but it receives no new events when the source is stopped.
Delete - I don't want to use this again
Deleting this solution permanently removes the project resources from the trial workspace. You can rebuild the same streaming paths from the project steps if you want to practise again.
- Return to the trial workspace item list.
- Open the item menu for DP700BikeStream.
- Select Delete.
- Confirm the deletion of DP700BikeStream.
- Open the item menu for DP700BikeOps.
- Select Delete.
- Confirm the deletion of DP700BikeOps.
- Refresh the trial workspace item list.
You should no longer see DP700BikeStream. You should no longer see DP700BikeOps.
Deleting the Eventhouse also removes its same-named KQL database. This includes RawBikeEvents, BikeMinuteMetrics, DockPressureAlerts, and DP700BikeValidation.kql.
Nice Work!
Nice Work!
Excellent work. Your bicycle availability monitor now uses Microsoft Fabric Eventstream to feed a two-path streaming solution in Eventhouse.
You've learned how to:
- Build a fan-out streaming pattern that preserves raw bicycle events in RawBikeEvents. Create one-minute street aggregates in BikeMinuteMetrics with tumbling windows.
- Compare Direct ingestion with Event processing before ingestion through visible table outputs. Validate active streets across multiple windows with Kusto Query Language (KQL).
- Use Data insights to interpret throughput plus backlog. Use Runtime logs to investigate warnings or errors. Right-size Event throughput to Low with one-day retention.
- Complete the optional Secret Mission by routing dock-pressure exceptions into DockPressureAlerts. Use a learner-selected No_Empty_Docks threshold to keep the exception path focused.
Ready to quiz yourself?