Prototype object
A prototype object is a single sObject held inside a Visualforce StandardSetController.
Definition
A prototype object is a single sObject held inside a Visualforce StandardSetController. When you set field values on this one record and then call save(), Salesforce copies those values onto every record in the controller's collection. That is what makes it the engine behind mass-update Visualforce pages.
The prototype object is not a separate object type you create in Setup. It is a runtime concept that lives inside the controller. You reach it in Apex with the getRecord() method, edit a field or two, and the StandardSetController applies the change across the whole selected set during the save action.
How the prototype object powers mass updates in Visualforce
What the prototype object actually is
The prototype object is a single sObject that the StandardSetController carries internally. Think of it as one blank record that stands in for the entire collection. You do not query it or insert it yourself. The controller creates it when you instantiate the StandardSetController, and it matches the object type of the records in the set. For an Account set controller, the prototype is an Account. For a Contact set controller, it is a Contact. The point of this single record is uniformity. When a page binds an input field to the prototype object and the user types a value, that value is staged in one place. On save, the StandardSetController writes the same value to every record the controller holds. So a rep can set a Region or a Status once and have it land on fifty records at the same time. The prototype object is the mechanism that turns one form field into a bulk edit, without you writing a loop in Apex to copy values record by record. It is a runtime helper, not a metadata object, so you will never find it listed in the Object Manager.
Reaching it with getRecord()
You access the prototype object in Apex through the StandardSetController method getRecord(). The official Apex Reference says getRecord() returns the sObject that represents the changes to the selected records, and that it is used for performing mass updates. So getRecord() and the prototype object are two names for the same thing seen from code. A common controller extension exposes it through a property. You might write a getter that returns ssc.getRecord() so a Visualforce page can bind inputs to it with apex:inputField. The page edits the prototype, not the individual rows. When the form posts back, the controller already knows which fields changed because they were changed on that one shared record. Keep in mind getRecord() on a StandardSetController behaves differently from getRecord() on a StandardController. The set controller version hands you the prototype for bulk edits across many records. The single controller version hands you the one record currently in context based on the id in the URL. Mixing those two up is a frequent source of confusion when developers move between detail pages and list pages.
The save action and what gets written
The save() method is where the prototype object earns its keep. When save() runs, the StandardSetController inserts new records or updates existing ones, then returns a PageReference back to the original page if it knows it, or to the home page. During that operation, any field you set on the prototype is applied to the records in the set. Fields you left untouched on the prototype are left alone on the underlying rows, so existing data is preserved and you do not accidentally blank out columns nobody edited. This is why the pattern suits mass updates so well. You are not assembling a list and calling update yourself. The controller does the DML inside save(). It also respects standard platform behavior, including field-level security, validation rules, and triggers on the object. If a validation rule blocks one record, the save can surface that error to the page through the standard ApexPages message mechanism. Treat save() like any other DML entry point. Plan for partial failures, governor limits, and the usual error handling that bulk operations require, especially when a single click might touch thousands of rows at once.
Selection: which records the change hits
The prototype object decides what changes. The selection decides which records receive it. A StandardSetController tracks a set of selected records, and you work with that set through getSelected() and setSelected(). On a list page, checkboxes drive the selection. In code, you can read the selected rows, filter them, or set the selection explicitly before saving. The interaction matters. If a user selects ten of forty rows and you set a field on the prototype, the save applies that field to the records the controller is operating on. Pair the prototype with a thoughtful selection model so users only bulk-edit what they meant to. getRecords() returns the full list of records in the current page set, which is useful for display, while getSelected() narrows it to the user's chosen rows. A good mass-update page shows the selected count clearly, so nobody is surprised when a single Status value lands on more records than they expected. It is also smart to add a confirmation step before save when the selection is large, since the prototype makes wide edits effortless and therefore easy to trigger by mistake.
Instantiation and the 10,000 record ceiling
You create a StandardSetController in Apex two ways. You can pass a List of sObjects, or you can pass a Database.QueryLocator. The choice changes behavior. A controller can work with up to 10,000 records, which is the standard governor ceiling for this class. If your query returns more, you handle the overflow yourself, usually by tightening filters or batching the work elsewhere. The instantiation method also affects filters. If you build the controller from a List and then call setFilterId(), the filter does not reduce the count. If you build it from a QueryLocator, setFilterId() and the standard list view filters apply as expected. There is an ordering rule too: call setPageSize() before setFilterId(), or the page size will not take effect. These quirks trip up developers who copy a List-based example and then wonder why list view filtering does nothing. When you need real list view behavior with paging, start from a QueryLocator. getListViewOptions() then returns the list views available to the current user, which you can show in a picklist so people choose the filter they want before the prototype edits begin.
Where it fits today and what to use instead
The prototype object is a Visualforce-era concept, and Visualforce is still fully supported. If you maintain a mass-update Visualforce page, the StandardSetController and its prototype object remain the simplest way to apply one set of values across many records with minimal code. The pattern is stable and worth understanding when you read or extend older controllers that other teams built years ago. For new work, Salesforce points teams toward Lightning Web Components and the Lightning Experience UI. There is no LWC equivalent named prototype object. Instead, you collect input in a component, build a list of records in JavaScript or Apex, and call an Apex method that performs the DML. Declarative options also cover many bulk edits now, including inline editing on list views, mass update actions from the list view, and tools like Flow. So treat the prototype object as a precise Visualforce mechanism, not a cross-platform pattern. Use it where Visualforce already lives, and reach for components, list view actions, or Flow when you start something new. Knowing the pattern still pays off, because plenty of production orgs run these pages today.
Trust & references
Cross-checked against the following references.
Straight from the source - Salesforce's reference material on Prototype object.
Hands-on resources to go deeper on Prototype object.
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Test your knowledge
Q1. What is the status of the term Prototype object in Salesforce?
Q2. If someone uses Prototype object informally on a Salesforce project, what do they most likely mean?
Q3. How should Salesforce communications refer to a draft object built for experimentation, instead of saying Prototype object?
Discussion
Loading discussion…