A parking management system sounds like a relatively simple application.
You have vehicles, parking spaces, permits, and a way to record violations. Add a dashboard, some CRUD endpoints, and a database, and the first version is ready.
But the interesting problems start when the system has to handle real-world situations.
A permit expires while a vehicle is parked. Someone changes their license plate. Two enforcement officers report the same vehicle. A parking rule changes, but an older violation still needs to be reviewed.
These are not just UI problems. They are data modeling, consistency, and system design problems.
Here are six considerations worth addressing early when building software for parking operations.
1. A Vehicle Is Not the Same Thing as a Permit
One tempting approach is to store a vehicle's license plate, assigned space, and permit status in a single table.
That works until the requirements change.
A resident may have multiple vehicles. A vehicle may be associated with different permits over time. A visitor may receive temporary authorization, while another vehicle has permission to use a space only during certain hours.
These are separate concepts with different lifecycles.
A more flexible model separates the entities:
vehicles: vehicle identifiers and relevant details
properties: locations where parking is managed
parking_spaces: spaces available at a property
permits: authorization to park under specific conditions
parking_events: observations and activity records
The relationships depend on the application's requirements, but separating these concepts avoids treating a temporary permission as a permanent property of a vehicle.
It also makes it easier to answer historical questions, such as whether a particular vehicle had valid authorization at a specific time.
2. Parking Permissions Are Time-Dependent
A field such as is_authorized = true seems convenient, but it doesn't represent the full picture.
Authorization may depend on the property, the vehicle, the permit's effective dates, and the rules that apply at a particular time.
For example, a visitor permit could be valid from 2 PM until 6 PM on Friday. The vehicle is authorized during that interval but not necessarily before or after it.
A simplified SQL table might look like this:
CREATE TABLE parking_permits (
id BIGINT PRIMARY KEY,
property_id BIGINT NOT NULL,
vehicle_id BIGINT NOT NULL,
valid_from TIMESTAMP NOT NULL,
valid_until TIMESTAMP NOT NULL,
status VARCHAR(20) NOT NULL,
CHECK (valid_until > valid_from)
);
This is only an illustrative starting point. A production schema would also need appropriate foreign keys, indexes, status constraints, and decisions about time zones and overlapping permissions.
The key idea is to model authorization as something that exists within a defined context and time period.
Historical decisions should not silently change just because a permit's current status changes.
3. You Need an Audit Trail, Not Just a Current State
Imagine that a vehicle is flagged for a parking violation, but the property manager later asks why it was flagged.
A database containing only the current permit status might not provide enough information to explain the decision.
Was the permit expired? Did the vehicle have a visitor authorization? Was an exception approved afterward? Which rule was applied?
A useful audit trail records significant events, including:
What happened.
When it happened.
Which user or service performed the action.
Which property and vehicle were involved.
Which rule or record was relevant to the decision.
For certain operations, recording the previous and updated values can also be useful.
The goal is not to log every insignificant database read. It is to preserve enough history to reconstruct important decisions.
This is particularly valuable in systems where records may later be reviewed by property managers, support teams, or authorized enforcement personnel.
4. Duplicate Events Are a Normal Failure Mode
Consider a mobile application used by an enforcement officer.
The officer submits a violation report, but the network connection drops before the application receives confirmation. The application retries the request.
Without additional safeguards, the backend may create two records for the same action.
This is a common distributed-systems problem: clients can retry requests, and the server may not know whether an earlier attempt succeeded.
One solution is to make operations idempotent where appropriate.
The client can send an idempotency key with a submission. The backend stores that key under a suitable uniqueness constraint and returns the existing result when the same request is retried.
Conceptually:
Client submits event with key K
|
v
Server checks whether K exists
|
+----+----+
| |
Exists New key
| |
Return Validate and
previous store event
result |
v
Return result
The implementation requires careful transaction handling, especially when creating related records or triggering downstream actions.
Not every pair of similar reports should automatically be treated as a duplicate, either. Two observations of the same vehicle may represent distinct events.
Idempotency keys help identify repeated submissions of the same operation; they are not a replacement for domain-specific duplicate detection.
5. Parking Rules Should Be Explicit and Versioned
Business rules tend to evolve.
A property might allow visitor parking for two hours during the week but use a different schedule on weekends. A new rule might take effect next month, while staff still need to review events that occurred under the previous policy.
Hardcoding these rules across controllers and frontend components makes changes difficult to maintain.
A better design separates rule evaluation from unrelated application logic.
For example, an authorization decision could take a defined set of inputs:
evaluateParkingAccess(
vehicle,
property,
permit,
eventTime,
applicableRules
)
The function would evaluate the supplied facts and return a decision with an explanation.
Keeping this logic isolated makes it easier to test edge cases such as expired permits, time restrictions, exceptions, and conflicting permissions.
For applications where decisions must be reviewed later, recording the applicable rule version can also be important. Otherwise, evaluating an old event using today's rules may produce a different result from the original decision.
6. Access Control Needs Property-Level Boundaries
Multi-tenant applications introduce another challenge: a user should only access the records they are authorized to see.
A property manager responsible for one location should not automatically gain access to every property's permits, vehicle records, or enforcement history.
Checking whether a user is authenticated is not enough. The application must also establish whether that user has permission to access the specific resource.
A backend authorization check should verify the user's role and relationship to the relevant property for each protected operation.
This applies to read requests as well as updates and deletions. Filtering records only in the frontend is not a security boundary.
Tests should cover cross-property access attempts, including cases where a user changes an identifier in a URL or API request.
For sensitive records, clear retention policies, controlled access to photographs, and appropriate audit logging are also worth considering.
Put the Domain Model Before the Dashboard
A well-designed interface cannot compensate for a data model that loses historical context, allows conflicting permissions, or fails to control access between properties.
Before investing heavily in the UI, define the core entities, relationships, time-dependent rules, event history, and authorization boundaries.
Then test realistic scenarios, not just the happy path.
What happens when a permit expires during a session? What if a mobile client retries a submission? What if a property changes its rules? Can an administrator explain why a past decision was made?
These questions often reveal architectural weaknesses much earlier than a production incident would.
For additional domain context, this overview of parking management software explains the broader operational workflows that such systems may need to support.
One question for other developers: When you build applications around real-world rules and permissions, which has caused you more trouble: modeling time correctly, maintaining an audit trail, handling duplicate events, or enforcing tenant boundaries?
I'd be interested in seeing what edge cases other people have encountered.
Top comments (0)