From Whiteboard to Production: Smart Parking on AWS
A few weeks ago, I sat down with a customer who told me something I hear more and more often. They are planning a smart parking solution, they want to build it on AWS and then came the honest part: “We don’t have the know how. We don’t know how to start. We just need your advice.”
The CIO didn’t come alone. He brought a few people from his technical team and they weren’t looking for a pitch, they wanted direction. They had already drafted an architecture and shared it with me. It was a good first attempt and was heading in the right direction, with only a few minor mistakes, but it wasn’t ready for production.
There were a few gaps in cost, in privacy, in how alerts would reach the right people, and in what happens when something fails, so I did the thing that tends to work better than a slide review. I invited them to our office, put a marker in my hand and we built it together, at least the starting point. I asked them to tell me, in plain words, what they wanted the solution to do. Then I drew it on the board one service at a time, saying out loud why each box earned its place. This article is that whiteboard, written down. It is a starting point for a smart parking, not a finished platform.
What they actually asked for
Know which vehicle is parked in each zone, check whether it has paid, give the driver time to pay before issuing a penalty, notify the right person when there is a real violation, and allow the parking operator to ask questions about what is happening.
That list is the architecture. Everything below exists to serve one of those five sentences.
Building a Smart Parking System
Plate recognition runs on the camera, not in the cloud. Each ANPR unit in Zone A, B and C reads the plate locally and publishes a small structured event: plate string, zone identifier, timestamp, confidence score, and a cropped image of the plate.
Cameras publish to AWS IoT Core over MQTT with TLS 1.2. Every camera holds its own X.509 certificate. That matters operationally more than it sounds: if one camera is stolen or tampered with, you revoke a single certificate.
Routing and evidence
An AWS IoT Rule sends each message in two directions. The cropped license plate image is stored in Amazon S3, while the event data triggers a Lambda function to check payment.
The image serves as evidence if a fine is disputed. Using the IoT Rules Engine for routing also avoids using Lambda just to decide where the data should go.
Payment validation and state
An AWS Lambda function checks Amazon DynamoDB for an active parking session keyed on plate and zone. There are three outcomes: an active session, an expired session, or no session at all. DynamoDB holds sessions, violations and cases in one table design, with single digit millisecond reads and on demand billing.
The grace period
No active payment does not immediately mean a violation. Drivers first receive a grace period of around 10–15 minutes.
The Lambda function starts an AWS Step Functions workflow, which waits during this period without keeping Lambda running. If the driver pays, the workflow ends and no fine is issued. If no payment is received, the violation is confirmed and saved in DynamoDB.
Step Functions also keeps a clear, timestamped record showing why and when the fine was issued.
Alerting
A confirmed violation publishes to an Amazon SNS topic. One topic fans out to email, SMS and mobile push, and the parking manager receives it on whichever channel they actually read. Adding a new recipient or channel later is a subscription, not a code change.
The operator console
Parking operators use a React web application hosted on Amazon S3 and delivered through Amazon CloudFront. Requests pass through Amazon API Gateway to a Lambda function. This Lambda is the only service allowed to access the parking data for the operator.
Get Ido Vapner’s stories in your inbox
Join Medium for free to get updates from this writer.
Amazon Bedrock helps the operator ask questions in simple language. Bedrock does not create SQL queries or access DynamoDB directly. It can only use four approved actions:
· Check a vehicle’s parking history
· Check how full a parking zone is
· Check the status of a violation
· Show open cases
Bedrock selects the right action, and Lambda runs a fixed and secure query. The result is then shown to the operator in simple language.
This approach reduces risk. Allowing an AI model to create its own queries could expose data it should not access or create unexpected costs. Limiting it to four approved actions makes the system easier to control, track, and audit.
What this diagram does not do yet
The Municipal Enforcement System is not connected automatically. This is intentional. Issuing a city parking ticket is a legal action, so a responsible person should review and approve it, especially in the first version of the system.
The design also has three missing parts:
- There is no policy for how long license plate images should be stored.
- There is no dead-letter queue to save failed or incorrect messages.
- There is no alert when a camera stops sending data.
The last point is important because a broken camera and an empty parking zone both produce the same result: no data..
The next step
Five things move this from whiteboard to production.
Add a human approval gate. Extend the Step Functions workflow with a wait for task token step before any ticket is dispatched. The operator approves or rejects in the console, and the decision is written to DynamoDB with the operator identity attached. This is the control that makes municipal integration defensible.
Connect the back office. Publish approved violations to Amazon EventBridge, with an SQS queue and a dead letter queue in front of the municipal system. Ticketing back offices go down, and you need the events to survive that.
Set a retention policy. Apply S3 Lifecycle rules that delete plate images once the appeal window closes, encrypt with AWS KMS, and keep the case record after the image is gone. Under GDPR, a plate is personal data, and “we kept it forever” is not a defensible position.
Detect silent failure. Have each camera publish a heartbeat, and raise a CloudWatch alarm when plate reads per zone drop below the expected floor for the hour. Night failures are the expensive ones.
Watch the cost. Tag every resource by zone, put an AWS Budgets alarm on the account, and track cost per thousand plate reads. That was the CIO’s real question, and it deserves a number rather than reassurance.
None of this is exotic. It is the difference between a design that demonstrates well and one that runs on a Tuesday night without anyone watching. That gap is where most smart parking or smart city projects stop, and closing it is mostly discipline, not technology










