Two ways to store a job-site address, benchmarked instead of argued about
Salesforce Location has a VisitorAddressId lookup to a real Address object. It looked like the right answer. Three DMLs, two records, and a circular delete later, plain fields won.
At Doorvana the property is a standard Location record — the garage door opening
belongs to a house, and that house outlives whoever owns it. Which raises a dull-sounding
question with a surprisingly sharp answer: where does the address go?
Salesforce offers two paths, and one of them looks obviously better on paper.
The path that looks right
Location ships with a VisitorAddressId field. It is not an address — it is a lookup to
a record of the standard Address object, which is fully writable and carries Street as a
textarea, City, StateCode and CountryCode as real picklists, PostalCode, and its own
latitude and longitude.
Compare that to hand-rolling Site_Street__c, Site_City__c, Site_State__c,
Site_Postal_Code__c and you appear to be reinventing something Salesforce already built,
including the state picklist.
So I built both and measured, rather than reasoning about it in a doc.
What the sandbox said
Three DML operations against one. But the row count is not what decided it.
The sharp edge: a circular delete
Location.VisitorAddressId points at the Address. Address.ParentId points back at the
Location. Neither record can be deleted while the other points at it, and both deletes
fail with the same unhelpful message:
could not be completed because it is associated with the following locations
Cleanup is a three-step dance in a fixed order:
- null out
Location.VisitorAddressId - delete the
Address - delete the
Location
For most objects that would be an annoyance. For a property base it is a real problem. Properties get merged, de-duplicated, corrected and retired over years — a wrong address typed once in 2027 is still there in 2032 unless someone can remove it. Making deletion a documented procedure rather than a delete button means, in practice, that nobody cleans up.
Two smaller findings in the same test, both disqualifying on their own:
Address.LocationTypeis required and its only available value is Virtual. Every job-site address would be stamped “Virtual”, forever.Address.AddressTypeoffers Mailing, Shipping, Billing and Home. There is no job-site value.
The standard object is not built for this. It is built for corporate addresses.
Correcting my own note while I was at it
I had written in the ERD that empty Lat/Long on Location would break Field Service dispatch. That is wrong, and testing it is what showed me.
Work Order and Service Appointment carry their own standard compound address fields, and routing uses those. A Location with no coordinates does not break scheduling. What it costs is geospatial reporting over the property base — mapping the sites served, analysing coverage by area — which is a real cost but a different one, and worth being accurate about when a client asks whether it matters.
The state field had to be rebuilt anyway
Choosing custom fields means giving up the StateCode picklist the Address object hands
you, and that mattered: with free text, “TX”, “Texas” and “tx” are three different states
and every report is quietly wrong.
So Site_State__c became a restricted picklist on a US_State global value set — 51 values,
Texas default. Which surfaced its own Salesforce limitation.
manifest/destructiveChangesPre.xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Location.Site_State__c</members>
<name>CustomField</name>
</types>
</Package> Worth knowing: the API name was reusable immediately, with no purge from Deleted Fields required. Verified afterwards by describe — picklist, restricted, 51 values, TX default.
One more thing fell out of the same pass. Site_City__c was 80 characters and
Site_State__c was shorter, which is inverted relative to the standard compound address
where City is 40. Nobody would notice until a migration out of these fields into standard
address fields truncated somebody’s city. Narrowed to 40 while it was free to do so.
Where this leaves the model
Four plain fields on Location, one of them a restricted picklist on a shared value set. One DML to create a property. A delete button that works.
The Address object is the more sophisticated answer, and for a company managing its own corporate sites it is probably the right one. For a property base that will accumulate tens of thousands of job sites and needs to stay clean, the boring version wins — and it won on numbers I could show the client rather than on taste.