aer 1.4
aer 1.4 extends every part of the local Apex workflow: the test runner reports coverage per test and runs test suites,
the development server accepts deployments of any metadata type and can store
its data in PostgreSQL, the VS Code extension reads your project configuration
from sfdx-project.json, and default flags can be kept in an .aerrc file.
Per-test code coverage
sfapex, Salesforce’s own Apex implementation, records which test method covered which lines of each class. aer now reports the same:
aer test force-app --json results.jsonl --coverage-per-testEach test record carries a perClassCoverage field listing the covered and
uncovered lines of every class the test touched. The coverage JSON written by
--coverage also lists each class’s covered lines in a coveredLines field
alongside the uncovered lines.
In VS Code, a new Run Apex Tests with Coverage profile in the Testing view runs the selected tests with coverage and shows covered and uncovered lines in the editor gutter and the Test Coverage view.
Test suites and other test runner additions
- Test suites.
aer test --suite <name>runs the classes named by a.testSuite-meta.xmlfile in your source. The suites are queryable asApexTestSuiteandTestSuiteMembershiprecords, andsf apex run test --suite-namesworks against the development server. - Permission set groups.
--assign-psgassigns permission set groups to the default user, the counterpart of--assign-perms. - Deployment-style validation.
--skip-mixed-dml-validationturns off theMIXED_DML_OPERATIONcheck, matching how sfapex runs tests during a deployment. - Live status. Sending
SIGUSR1to a runningaer testprocess prints a one-line status summary, including the setup phase and elapsed time before tests start. - Faster reruns. A rerun over unchanged sources restores a cached workspace image and skips parsing, semantic analysis, type checking, and symbol resolution.
- Packages as source. A
.pkgfile passed as a source path, or left inside a source directory, loads as an unmanaged package with no--packageflag. Its test classes are discovered and run like your own.
VS Code reads sfdx-project.json
The VS Code extension now derives its configuration from
sfdx-project.json. Source paths come from packageDirectories, the default
namespace from namespace, and replacements are applied by staging source
into a temporary directory before running, matching what
sf project deploy start would deploy. Each package directory’s
unpackagedMetadata is loaded alongside the packaged source, and
apexTestAccess.permissionSets are passed to aer as --assign-perms.
The language server, test runner, watch mode, and debugger all use these
settings, and failure locations in staged files map back to the real files.
The aer.useSfdxProject setting is on by default; explicit aer.sourcePaths
and aer.defaultNamespace settings still take precedence.
Development server
aer server exists so you can preview Lightning Web Components and UI
Bundles, and exercise the Salesforce APIs from scripts and integration tests,
without deploying to an org. This release makes it easier
to iterate against the server and widens the APIs it answers.
Deploy any metadata type without restarting
The server’s deploy endpoints previously handled Apex classes, single-file custom objects, and a narrow set of destructive changes. Deployments are now imported with the same metadata walker aer uses at startup, so a standard deployment from the Salesforce CLI can add or change objects and fields, triggers, flows, flexipages, workflow rules, permission sets, profiles, custom metadata records, queues, labels, value sets, static resources, Visualforce pages, email templates, reports, and dashboards while the server keeps running:
sf project deploy start --source-dir force-app -o aer
sf project deploy start --source-dir force-app -o aer --dry-runEach deployment compiles Apex against the merged schema, validates
package.xml members the way the Metadata API does, and rolls back on
failure. A deployment that changes only Apex no longer triggers a schema
reload.
Endpoint browser
The landing page is now an endpoint browser. It lists every development tool
and API endpoint the server exposes, grouped by category, with a search box
(press / to focus it), a copy button for each path, and a status indicator
that shows whether the server is still responding. The endpoint list is built
from the live routes, so Apex REST classes from your source appear alongside
the built-in endpoints. The preview, monitoring, and explorer pages share the
same design with a light and dark theme.
More of the API surface
- Tooling API.
MetadataContainer,ApexClassMember, andContainerAsyncRequestimplement the container save path IDE integrations use,MetadataComponentDependencyqueries come from aer’s dependency graph, andrunTestsSynchronousruns a test class and records coverage inApexCodeCoverage. - Analytics API.
analytics/reportsandanalytics/dashboardsrun reports and dashboards from your source and returnfactMap-shaped results, so code that consumes report data can be tested locally. The report engine behind them gained row-level formulas, joined reports, bucket fields, activity reports, and custom report types. - UI Bundles. The Data SDK shim resolves
@salesforce/platform-sdk, and bundles are served at the GA/app/c__<bundleName>URL. - REST and Bulk writes run the full DML pipeline. A record written through those endpoints fires the same triggers, flows, workflow rules, and validation rules an Apex insert would, and each row reports its own errors.
- Pre-shared session tokens.
--seed-session-tokenregisters a token as an authenticated session at startup, so a script or CI job can log in withsf org login access-tokenwithout a browser. - The default API version is now 67.0.
PostgreSQL storage
The exec, test, and server commands accept --db postgres://… to store
data in a PostgreSQL database instead of the embedded SQLite store, and
--db postgresqltest:// starts a private, disposable PostgreSQL server for
the run. The schema uses identity columns and PL/pgSQL triggers, the formula
and SOQL functions are installed as database functions, and text comparison
uses a collation that matches sfapex. SELECT … FOR UPDATE takes row locks in
the database, and a lock timeout raises a QueryException with
UNABLE_TO_LOCK_ROW, the same error sfapex raises.
Keeping data between sessions
A server started with --db keeps its data between runs. Several changes
make that smoother. A restart against an unchanged project attaches to the
existing database without re-migrating tables or reseeding metadata.
Upgrading aer no longer requires rebuilding the database. --bootstrap-db
merges into the existing data rather than wiping it first. Session tokens are
stored in the database, so a login survives a restart.
Reliability under concurrent requests
A page that makes many requests at once, or an integration test that runs in parallel, exercised bugs that are now fixed. Apex REST requests leaked pooled VMs until the pool was exhausted and the server stopped responding. Concurrent requests shared a storage transaction, which produced 500s and lost writes. A deployment could panic against in-flight execution. Each has an explicit fix, and the async job worker now wakes only when async work was actually enqueued.
Configuration
.aerrcfiles hold default flags so they need not be repeated on every invocation. Files are read from$XDG_CONFIG_HOME/aer/aerrc,~/.aerrc, and./.aerrc, in increasing precedence. An explicit command-line flag wins, and a flag not defined on the invoked command is dropped, so one file can hold defaults for several commands.aer --help-aerrcexplains the format.--localeand--currencyset the org’s default locale and currency, alongside the existing--timezone.--allow-emaildeliversMessaging.sendEmailover SMTP. Without the flag, email is validated and logged but not sent, as before.
Platform coverage
- Revenue Cloud. The full Agentforce Revenue Management SObject suite is
modeled behind the
RevenueCloudfeature, including the field derivations and status restrictions sfapex enforces onOrder,FulfillmentOrder, and accounting periods. - Flows. A record-triggered flow now saves once per element rather than
once per record, matching the Flow runtime’s bulkification. Transform
elements,
REGEXin formulas,$Flow.CurrentDatetyping, and null handling were also corrected. The changelog lists 37 Flow fixes. - Approval processes. An approval process runs from your
approvalProcessesmetadata, and each step’s entry criteria now decide whether a submitted record enters that step: a record that fails them skips the step, so an approver field guarded by a criterion no longer fails the submission, and running out of steps completes the approval. An approval’s field updates save through the DML pipeline, so the object’s triggers, workflow rules, and record-triggered flows run. Submitting a record that already has a pending approval fails withALREADY_IN_PROCESS, andApproval.ProcessWorkitemRequestrejects an unknown or null action rather than treating it as a successful transition. Workflow and approval criteria also gained the relational operations, which previously evaluated false and silently disabled every rule resting on them. - Duplicate rules. Duplicate rules are enforced on insert and update DML,
with the fuzzy name, company, and address matching algorithms. A rule now
participates in an update only when that update changes a field its matching
rule matches on, so editing an unrelated field no longer fails the save with
DUPLICATES_DETECTEDover a duplicate the record already had. - Test data isolation. A test without
SeeAllDatano longer sees rows it did not write. A committed org row, from a bootstrap database or seeded metadata, is hidden from SOQL, aggregates, query locators, SOSL, semi-joins, child subqueries, and duplicate-rule matching, while staying addressable for insert, update, and delete. Setup and metadata objects stay visible. - Fixes. The changelog lists 169 fixes in this release, covering SOQL null semantics, formula field inlining, workflow and approval criteria, LWC compilation, person accounts, JSON parsing, Visualforce components, and coverage accounting. If aer behaved differently from Salesforce on something you rely on, check the CHANGELOG before working around it.
Upgrading
brew upgrade aer
# or
aer upgradeIf the Salesforce CLI plugin downloaded its own copy of aer, it checks for a
newer release on a later run and offers to install it. sf plugins update
updates the plugin itself, not that copy. The VS Code extension updates
through the Marketplace. Its minimum VS Code
version is now 1.88.0, where the test coverage API was finalized.
See Development Server, Configuration, and Interactive Debugging for the documentation of these features.