Bike Rental Shop Backend Variants

Compare the synchronized and concurrent BikeRentalShop backends while keeping the same API contract, packaging approach, and web-client integration points.

Full source

Files:

# Start the real BikeRentalShop synchronized and concurrent services directly.
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Synchronized\Service.ps1 -Port 5443
pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Concurrent\Service.ps1 -Port 5444

Step-by-step

  1. Entry point: The two backend entry scripts live under pwsh/tutorial/examples/BikeRentalShop/Synchronized/Service.ps1 and pwsh/tutorial/examples/BikeRentalShop/Concurrent/Service.ps1.
  2. Shared contract: Both variants expose the same customer routes, staff routes, API key requirement, and OpenAPI surface.
  3. Synchronized model: The synchronized backend keeps a familiar PowerShell object graph and serializes compound updates behind one lock.
  4. Concurrent model: The concurrent backend stores state in concurrent dictionaries but still protects multi-record mutations and persistence with a lock.
  5. Persistence: Both variants export state under their own data/ folders so restarts preserve bikes and rental history.
  6. Packaging: Both are package-ready services that can be shipped with New-KrServicePackage without rewriting the host script.
  7. Browser compatibility: Both can accept the same -AllowedCorsOrigins values so the standalone web client can target either backend.
  8. Swap story: Because the API shape is stable, clients can move between variants without changing their request payloads or routes.

Try it

Start the synchronized variant:

pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Synchronized\Service.ps1 -Port 5443

Start the concurrent variant:

pwsh .\docs\_includes\examples\pwsh\BikeRentalShop\Concurrent\Service.ps1 -Port 5444

Compare the same API calls against both services:

Invoke-RestMethod -Uri 'https://127.0.0.1:5443/api/bikes' -SkipCertificateCheck
Invoke-RestMethod -Uri 'https://127.0.0.1:5444/api/bikes' -SkipCertificateCheck

Invoke-RestMethod -Uri 'https://127.0.0.1:5443/api/staff/dashboard' `
    -Headers @{ 'X-Api-Key' = 'bike-shop-demo-key' } `
    -SkipCertificateCheck

Invoke-RestMethod -Uri 'https://127.0.0.1:5444/api/staff/dashboard' `
    -Headers @{ 'X-Api-Key' = 'bike-shop-demo-key' } `
    -SkipCertificateCheck

What changes between the variants

  • Synchronized optimizes for readability and a straightforward PowerShell object model.
  • Concurrent optimizes for a more explicit concurrent collection story inside the in-memory store.
  • Both still lock around compound operations like rental creation and returns so inventory and rental records stay consistent.
  • Both publish the same external API, which makes them useful for experimentation without breaking callers.

Choosing a backend

  • Choose Synchronized when you want the clearest walkthrough of shared-state initialization, route logic, and persistence.
  • Choose Concurrent when you want the sample to demonstrate concurrent dictionaries end to end.
  • Use the standalone Web/ client when you want to compare both backends through the same browser experience.

Troubleshooting

Symptom Cause Fix
The wrong backend is running The synchronized and concurrent services were started on unexpected ports Start the exact service script you want to compare and keep the ports distinct
The variants behave differently for the same request Their persisted data/ folders no longer contain the same seed state Clear or compare the respective data/ folders before re-running the scenario
The web client works with one variant but not the other One backend was started without matching -AllowedCorsOrigins Start both variants with the same allowed origin list when comparing browser behavior
Packaging output differs unexpectedly You packaged different source folders Package each backend from its own folder: Synchronized/ or Concurrent/

References


Previous / Next

Previous: Bike Rental Shop Web Client Next: Bike Rental Shop Packaging