<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged sas</title>
<link>https://coderlegion.com/tag/sas</link>
<description>Powered by Question2Answer</description>
<item>
<title>The Legacy Report Was Going Away. The Agent Still Needed the Answer.</title>
<link>https://coderlegion.com/32464/the-legacy-report-was-going-away-the-agent-still-needed-the-answer</link>
<description>&lt;p&gt;&lt;em&gt;An anonymized banking modernization case study about replacing SAS-backed operational reports with APIs that agents could use in Salesforce.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine an agent opening a fraud or exception report during a customer call. The report appears in a legacy system, but the agent’s real task is to make a timely, authorized decision. If the system is retired and the same answer becomes slow, incomplete, or visible to the wrong person, the migration has failed—even if the new application looks better.&lt;/p&gt;
&lt;p&gt;That was the challenge in a banking modernization program I worked on. Operational and business reporting functionality hosted on SAS needed to move into a Salesforce-centered workflow. My responsibilities included designing Spring Boot GET APIs for several report domains, connecting the service to Snowflake, applying agent role-based access, and exposing the endpoints to the Salesforce team. The architecture below is deliberately simplified; it describes the engineering pattern without disclosing internal systems or customer data.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9107409727456458812&quot; alt=&quot;Simplified architecture: agent in Salesforce requests a report through a role-aware Spring Boot API backed by Snowflake&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;first-migrate-the-decision-not-the-screen&quot;&gt;First, migrate the decision—not the screen&lt;/h3&gt;
&lt;p&gt;A legacy report often contains more than a table. It can encode filters, calculations, refresh timing, exception definitions, and the habits people have built around it. Copying its columns into a new UI does not prove that an agent receives the same answer.&lt;/p&gt;
&lt;p&gt;For each report, the useful questions were: &lt;strong&gt;Who uses it? Which decision does it support? What does each field mean? How fresh must it be? What should happen when the data is missing?&lt;/strong&gt; These questions turn a screen replacement into a contract that the new service can implement and test.&lt;/p&gt;
&lt;p&gt;An example is an exception report. A row count can match while the underlying definition of “open” changes, or a date filter shifts at midnight in a different time zone. The result looks plausible, but an agent may follow up on the wrong cases. A migration test therefore needs representative records and business-rule comparisons, not only a schema check.&lt;/p&gt;
&lt;h3 id=&quot;put-a-stable-api-between-salesforce-and-reporting-data&quot;&gt;Put a stable API between Salesforce and reporting data&lt;/h3&gt;
&lt;p&gt;We used RESTful GET endpoints to give the Salesforce experience a focused way to request report data. A service layer can validate inputs, apply business rules, authorize the caller, query Snowflake, and return a consistent response contract. It also gives the UI team a stable interface while the data or report logic evolves behind it.&lt;/p&gt;
&lt;p&gt;Salesforce documents a &lt;strong&gt;request-and-reply&lt;/strong&gt; integration pattern for user actions that call an external system and wait for the result. That pattern is useful for interactive reporting, but it makes latency and failure behavior part of the user experience. A timeout is not an empty report. The API should distinguish “no matching records” from “the source was unavailable,” use bounded queries and pagination where appropriate, and make error states clear enough for the UI to handle.&lt;/p&gt;
&lt;p&gt;This service boundary also limits how much reporting logic leaks into the frontend. The API should expose business concepts the agent understands rather than Snowflake table names or a direct translation of old SAS implementation details.&lt;/p&gt;
&lt;h3 id=&quot;access-control-must-follow-the-data-all-the-way-through&quot;&gt;Access control must follow the data all the way through&lt;/h3&gt;
&lt;p&gt;“The agent is signed into Salesforce” is only the start of an authorization decision. The backend still needs to know which report and which records that agent may access. Role checks at the API boundary protect the endpoint; data-scoped controls protect the result set. The two should agree, and denied access should be tested as carefully as successful access.&lt;/p&gt;
&lt;p&gt;Snowflake supports row access policies that determine which rows a query returns. They are one possible defense in depth, subject to the organization’s roles and policy design. They also affect query behavior and performance, so access rules should be validated with realistic report requests. The point is broader than a particular Snowflake feature: &lt;strong&gt;a correct report returned to the wrong role is a production defect.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For a banking workflow, logs and traces also need restraint. A useful audit trail records who requested which report, when, and whether it succeeded. It does not need to dump sensitive report contents into application logs.&lt;/p&gt;
&lt;h3 id=&quot;prove-the-new-path-under-production-like-conditions&quot;&gt;Prove the new path under production-like conditions&lt;/h3&gt;
&lt;p&gt;Functional tests answer whether the endpoint returns the right data for a known case. They do not answer whether a team of agents can use it at the same time on a busy morning. We developed performance tests with JMeter and Gatling to exercise the services against SLA requirements under load.&lt;/p&gt;
&lt;p&gt;A meaningful test model includes the report mix, concurrent users, query sizes, authorized and unauthorized requests, and the effect of a slow data source. Measure end-to-end response time from the agent-facing API, not just the time taken by one SQL query. Check the long tail as well as the average. If a report is large, test pagination and the cost of repeated requests. If a dependency fails, verify that the service fails clearly and recovers.&lt;/p&gt;
&lt;p&gt;I would also treat the cutover as a comparison exercise: sample the same business cases through the legacy and new paths, explain any differences, and have report owners validate them. Where old behavior was wrong, document the intended correction explicitly. Otherwise a “fixed” report can look like an unexplained regression to the people using it.&lt;/p&gt;
&lt;h3 id=&quot;what-this-kind-of-migration-teaches&quot;&gt;What this kind of migration teaches&lt;/h3&gt;
&lt;p&gt;The visible technology changes from SAS reports to Salesforce screens, Spring Boot APIs, and Snowflake queries. The hard part is preserving the &lt;strong&gt;meaning, access, and timing&lt;/strong&gt; of the answer that an agent needs.&lt;/p&gt;
&lt;p&gt;The reusable sequence is straightforward: inventory the decisions supported by each report; define the API contract and data semantics; enforce access at the service and data layers; compare old and new results; test peak traffic and failure modes; then cut over with clear ownership of discrepancies. That is how a platform retirement becomes a reliable workflow change instead of a prettier route to the wrong answer.&lt;/p&gt;
&lt;p&gt;What has been the hardest part of a legacy reporting migration in your experience: report logic, data quality, access control, or cutover?&lt;/p&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Salesforce, &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.salesforce.com/docs/atlas.en-us.integration_patterns_and_practices.meta/integ_pat_patterns_platform.htm&quot;&gt;Integration Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Snowflake, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.snowflake.com/en/user-guide/security-row-intro&quot;&gt;Understanding row access policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Apache JMeter, &lt;a rel=&quot;nofollow&quot; href=&quot;https://jmeter.apache.org/usermanual/index.html&quot;&gt;User's Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gatling, &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.gatling.io/&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32464/the-legacy-report-was-going-away-the-agent-still-needed-the-answer</guid>
<pubDate>Mon, 26 Oct 2026 04:08:02 +0000</pubDate>
</item>
</channel>
</rss>