Software Articles / Blogs / Perficient https://blogs.perficient.com/category/services/innovation-product-development/development/software/ Expert Digital Insights Mon, 16 Feb 2026 21:33:33 +0000 en-US hourly 1 https://blogs.perficient.com/files/favicon-194x194-1-150x150.png Software Articles / Blogs / Perficient https://blogs.perficient.com/category/services/innovation-product-development/development/software/ 32 32 30508587 Language Mastery as the New Frontier of Software Development https://blogs.perficient.com/2026/02/16/language-mastery-as-the-new-frontier-of-software-development/ https://blogs.perficient.com/2026/02/16/language-mastery-as-the-new-frontier-of-software-development/#respond Mon, 16 Feb 2026 17:23:54 +0000 https://blogs.perficient.com/?p=390355
In the current technological landscape, the interaction between human developers and Large Language Models (LLMs) has transitioned from a peripheral experiment into a core technical competency. We are witnessing a fundamental shift in software development: the evolution from traditional code logic to language logic. This discipline, known as Prompt Engineering, is not merely about “chatting” with an AI; it is the structured ability to translate human intent into precise machine action. For the modern software engineer, designing and refining instructions is now as critical as writing clean, executable code.

1. Technical Foundations: From Prediction to Instruction

To master AI-assisted development, one must first understand the nature of the model. An LLM, at its core, is a probabilistic prediction engine. When given a sequence of text, it calculates the most likely next word (or token) based on vast datasets.
Base Models vs. Instruct Models
Technical proficiency requires a distinction between Base Models and Instruct Models. A Base LLM is designed for simple pattern completion or “autocomplete.” If asked to classify a text, a base model might simply provide another example of a text rather than performing the classification. Professional software development relies almost exclusively on Instruct Models. These models have been aligned through Reinforcement Learning from Human Feedback (RLHF) to follow explicit directions rather than just continuing a text pattern.
The fundamental paradigm of this interaction is simple but absolute: the quality of the input (the prompt) directly dictates the quality and accuracy of the output (the response).

2. The Two Pillars of Effective Prompting

Every successful interaction with an LLM rests on two non-negotiable principles. Neglecting either leads to unpredictable, generic, or logically flawed results.
1. Clarity and Specificity

Ambiguity is the primary enemy of quality AI output. Models cannot read a developer’s mind or infer hidden contexts that are omitted from the prompt. When an instruction is vague, the model is forced to “guess,” often resulting in a generic “average response” that fails to meet specific technical requirements. A specific prompt must act as an explicit manual. For instance, rather than asking to “summarize an email,” a professional prompt specifies the role (Executive Assistant), the target audience (a Senior Manager), the focus (required actions and deadlines), and the formatting constraints (three key bullet points).

Vague Prompt (Avoid) Specific Prompt (Corporate Standard)
“Summarize this email.” “Act as an executive assistant. Summarize the following email in 3 key bullet points for my manager. Focus on required actions and deadlines. Omit greetings.”
“Do something about marketing.” “Generate 5 Instagram post ideas for the launch of a new tech product, each including an opening hook and a call-to-action.”

 

 

2. Allowing Time for Reasoning
LLMs are prone to logical errors when forced to provide a final answer immediately—a phenomenon described as “impulsive reasoning.” This is particularly evident in mathematical logic or complex architectural problems. The solution is to explicitly instruct the model to “think step-by-step.” This technique, known as Chain-of-Thought (CoT), forces the model to calculate intermediate steps and verify its own logic before concluding. By breaking a complex task into a sequence of simpler sub-tasks, the reliability of the output increases exponentially.
3. Precision Structuring Tactics
To transform a vague request into a high-precision technical order, developers should utilize five specific tactics.
• Role Assignment (Persona): Assigning a persona—such as “Software Architect” or “Cybersecurity Expert”—activates specific technical vocabularies and restricts the model’s probabilistic space toward expert-level responses. It moves the AI away from general knowledge toward specialized domain expertise.
• Audience and Tone Definition: It is imperative to specify the recipient of the information. Explaining a SQL injection to a non-technical manager requires a completely different lexicon and level of abstraction than explaining it to a peer developer.
• Task Specification: The central instruction must be a clear, measurable action. A well-defined task eliminates ambiguity regarding the expected outcome.
• Contextual Background: Because models lack access to private internal data or specific business logic, developers must provide the necessary background information, project constraints, and specific data within the prompt ecosystem.
• Output Formatting: For software integration, leaving the format to chance is unacceptable. Demanding predictable structures—such as JSON arrays, Markdown tables, or specific code blocks—is critical for programmatic parsing and consistency.
Technical Delimiters Protocol
To prevent “Prompt Injection” and ensure application robustness, instructions must be isolated from data using:
• Triple quotes (“””): For large blocks of text.
• Triple backticks (`): For code snippets or technical data.
• XML tags (<tag>): Recommended standard for organizing hierarchical information.
• Hash symbols (###): Used to separate sections of instructions.
Once the basic structure is mastered, the standard should address highly complex tasks using advanced reasoning.
4. Advanced Reasoning and In-Context Learning
Advanced development requires moving beyond simple “asking” to “training in the moment,” a concept known as In-Context Learning.
Shot Prompting: Zero, One, and Few-Shot
• Zero-Shot: Requesting a task directly without examples. This works best for common, direct tasks the model knows well.
• One-Shot: Including a single example to establish a basic pattern or format.
• Few-Shot: Providing multiple examples (usually 2 to 5). This allows the model to learn complex data classification or extraction patterns by identifying the underlying rule from the history of the conversation.
Task Decomposition
This involves breaking down a massive, complex process into a pipeline of simpler, sequential actions. For example, rather than asking for a full feature implementation in one go, a developer might instruct the model to: 1. Extract the data requirements, 2. Design the data models, 3. Create the repository logic, and 4. Implement the UI. This grants the developer superior control and allows for validation at each intermediate step.
ReAct (Reasoning and Acting)
ReAct is a technique that combines reasoning with external actions. It allows the model to alternate between “thinking” and “acting”—such as calling an API, performing a web search, or using a specific tool—to ground its final response in verifiable, up-to-date data. This drastically reduces hallucinations by ensuring the AI doesn’t rely solely on its static training data.
5. Context Engineering: The Data Ecosystem
Prompting is only one component of a larger system. Context Engineering is the design and control of the entire environment the model “sees” before generating a response, including conversation history, attached documents, and metadata.
Three Strategies for Model Enhancement
1. Prompt Engineering: Designing structured instructions. It is fast and cost-free but limited by the context window’s token limit.
2. RAG (Retrieval-Augmented Generation): This technique retrieves relevant documents from an external database (often a vector database) and injects that information into the prompt. It is the gold standard for handling dynamic, frequently changing, or private company data without the need to retrain the model.
3. Fine-Tuning: Retraining a base model on a specific dataset to specialize it in a particular style, vocabulary, or domain. This is a costly and slow strategy, typically reserved for cases where prompting and RAG are insufficient.
The industry “Golden Rule” is to start with Prompt Engineering, add RAG if external data is required, and use Fine-Tuning only as a last resort for deep specialization.
6. Technical Optimization and the Context Window
The context window is the “working memory” of the model, measured in tokens. A token is roughly equivalent to 0.75 words in English or 0.25 words in Spanish. Managing this window is a technical necessity for four reasons:
• Cost: Billing is usually based on the total tokens processed (input plus output).
• Latency: Larger contexts require longer processing times, which is critical for real-time applications.
• Forgetfulness: Once the window is full, the model begins to lose information from the beginning of the session.
• Lost in the Middle: Models tend to ignore information located in the center of extremely long contexts, focusing their attention only on the beginning and the end.
Optimization Strategies
Effective context management involves progressive summarization of old messages, utilizing “sliding windows” to keep only the most recent interactions, and employing context caching to reuse static information without incurring reprocessing costs.
7. Markdown: The Communication Standard

Markdown has emerged as the de facto standard for communicating with LLMs. It is preferred over HTML or XML because of its token efficiency and clear visual hierarchy. Its predictable syntax makes it easy for models to parse structure automatically. In software documentation, Markdown facilitates the clear separation of instructions, code blocks, and expected results, enhancing the model’s ability to understand technical specifications.

Token Efficiency Analysis

The choice of format directly impacts cost and latency:

  • Markdown (# Title): 3 tokens.
  • HTML (<h1>Title</h1>): 7 tokens.
  • XML (<title>...</title>): 10 tokens.

Corporate Syntax Manual

Element Syntax Impact on LLM
Hierarchy # / ## / ### Defines information architecture.
Emphasis **bold** Highlights critical constraints.
Isolation ``` Separates code and data from instructions.

 

8. Contextualization for AI Coding Agents
AI coding agents like Cursor or GitHub Copilot require specific files that function as “READMEs for machines.” These files provide the necessary context regarding project architecture, coding styles, and workflows to ensure generated code integrates seamlessly into the repository.
• AGENTS.md: A standardized file in the repository root that summarizes technical rules, folder structures, and test commands.
• CLAUDE.md: Specific to Anthropic models, providing persistent memory and project instructions.
• INSTRUCTIONS.md: Used by tools like GitHub Copilot to understand repository-specific validation and testing flows.
By placing these files in nested subdirectories, developers can optimize the context window; the agent will prioritize the local context of the folder it is working in over the general project instructions, reducing noise.
9. Dynamic Context: Anthropic Skills
One of the most powerful innovations in context management is the implementation of “Skills.” Instead of saturating the context window with every possible instruction at the start, Skills allow information to be loaded in stages as needed.
A Skill consists of three levels:
1. Metadata: Discovery information in YAML format, consuming minimal tokens so the model knows the skill exists.
2. Instructions: Procedural knowledge and best practices that only enter the context window when the model triggers the skill based on the prompt.
3. Resources: Executable scripts, templates, or references that are launched automatically on demand.
This dynamic approach allows for a library of thousands of rules—such as a company’s entire design system or testing protocols—to be available without overwhelming the AI’s active memory.
10. Workflow Context Typologies
To structure AI-assisted development effectively, three types of context should be implemented:
1. Project Context (Persistent): Defines the tech stack, architecture, and critical dependencies (e.g., PROJECT_CONTEXT.md).
2. Workflow Context (Persistent): Specifies how the AI should act during repetitive tasks like bug fixing, refactoring, or creating new features (e.g., WORKFLOW_FEATURE.md).
3. Specific Context (Temporary): Information created for a specific session or a single complex task (e.g., an error analysis or a migration plan) and deleted once the task is complete.
A practical example of this is the migration of legacy code. A developer can define a specific migration workflow that includes manual validation steps, turning the AI into a highly efficient and controlled refactoring tool rather than a source of technical debt.
Conclusion: The Role of the Context Architect
In the era of AI-assisted programming, success does not rely solely on the raw power of the models. It depends on the software engineer’s ability to orchestrate dialogue and manage the input data ecosystem. By mastering prompt engineering tactics and the structures of context engineering, developers transform LLMs from simple text assistants into sophisticated development companions. The modern developer is evolving into a “Context Architect,” responsible for directing the generative capacity of the AI toward technical excellence and architectural integrity. Mastery of language logic is no longer optional; it is the definitive tool of the Software Engineer 2.0.
]]>
https://blogs.perficient.com/2026/02/16/language-mastery-as-the-new-frontier-of-software-development/feed/ 0 390355
Upgrading from Gulp to Heft in SPFx | Sharepoint https://blogs.perficient.com/2026/01/14/upgrading-from-gulp-to-heft-in-spfx-sharepoint/ https://blogs.perficient.com/2026/01/14/upgrading-from-gulp-to-heft-in-spfx-sharepoint/#respond Wed, 14 Jan 2026 09:59:20 +0000 https://blogs.perficient.com/?p=389727

With the release of SPFx v1.22, Microsoft introduced Heft as the new build engine, replacing Gulp. This change brings better performance, modern tooling, and a more standardized approach to building SPFx solutions. In this blog, we’ll explore what this means for developers and how to upgrade.

What is Gulp in SPFx?

In SharePoint Framework (SPFx), Gulp is a JavaScript-based task runner that was traditionally used to automate build and development tasks.

What Gulp Did in SPFx

Historically, the SharePoint Framework (SPFx) relied on Gulp as its primary task runner, responsible for orchestrating the entire build pipeline. Gulp did a series of scripted tasks, defined inside gulpfile.js and in different SPFx build rig packages. These tasks automate important development and packaging workflows.These tasks included:

  • Automates repetitive tasks such as:
    • TypeScript to JavaScript.
    • Bundling multiple files into optimized packages.
    • Minifying code for better performance.
    • Packaging the solution into a “.sppkg” file for deployment.
  • Runs development servers for testing (gulp serve).
  • Watches for changes and rebuilds automatically during development

Because these tasks depended on ad‑hoc JavaScript streams and SPFx‑specific build rig wrappers, the pipeline could become complex and difficult to extend consistently across projects.

The following are the common commands included in gulp:

  • gulp serve – local workbench/dev server
  • gulp build – build the solution
  • gulp bundle – produce deployable bundles
  • gulp package-solution – create the .sppkg for the App Catalog

What is Heft?

In SharePoint Framework (SPFx), Heft is the new build engine introduced by Microsoft, starting with SPFx v1.22. It replaces the older Gulp-based build system.

Heft has replaced Gulp to support modern architecture, improve performance, ensure consistency and standardization, and provide greater extensibility.

Comparison between heft and gulp:

Area Gulp (Legacy) Heft (SPFx v1.22+)
Core model Task runner with custom JS/streams (gulpfile.js) Config‑driven orchestrator with plugins/rigs
Extensibility Write custom tasks per project Use Heft plugins or small “patch” files; standardized rigs
Performance Sequential tasks; no native caching Incremental builds, caching, unified TypeScript pass
Config surface Often scattered across gulpfile.js and build rig packages Centralized JSON/JS configs (heft.json, Webpack patch/customize hooks)
Scale Harder to keep consistent across many repos Designed to scale consistently (Rush Stack)

Installation Steps for Heft

  • To work with the upgraded version, you need to install Node v22.
  • Run the command npm install @rushstack/heft –global

Removing Gulp from an SPFx Project and Adding Heft (Clean Steps)

  • To work with the upgraded version, install Node v22.
  • Remove your current node_modules and package-lock.json, and run npm install again
  • NOTE: deleting node_modules can take a very long time if you don’t skip the recycle bin.
    • Open PowerShell
    • Navigate to your Project folder
    • Run command Remove-Item -Recurse -Force node_modules
    • Run command Remove-Item -Force package-lock.json
  • Open the solution in VS Code
  • In terminal run command npm cache clean –force
  • Then run npm install
  • Run the command npm install @rushstack/heft –global

After that, everything should work, and you will be using the latest version of SPFx with heft. However, going forward, there are some commands to be aware of

Day‑to‑day Commands on Heft

  • heft clean → cleans build artifacts (eq. gulp clean)
  • heft build → compiles & bundles (eq. gulp build/bundle) (Note— prod settings are driven by config rather than –ship flags.)
  • heft start → dev server (eq. gulp serve)
  • heft package-solution → creates.sppkg (dev build)
  • heft package-solution –production → .sppkg for production (eq. gulp package-solution –ship)
  • heft trust-dev-cert → trusts the local dev certificate used by the dev server (handy if debugging fails due to HTTPS cert issues

Conclusion

Upgrading from Gulp to Heft in SPFx projects marks a significant step toward modernizing the build pipeline. Heft uses a standard, configuration-based approach that improves performance, makes things the same across projects, and can be expanded for future needs. By adopting Heft, developers align with Microsoft’s latest architecture, reduce maintenance overhead, and gain a more scalable and reliable development experience.

]]>
https://blogs.perficient.com/2026/01/14/upgrading-from-gulp-to-heft-in-spfx-sharepoint/feed/ 0 389727
From Legacy to Modern: Migrating WCF to Web API with the Help of AI https://blogs.perficient.com/2026/01/13/from-legacy-to-modern-migrating-wcf-to-web-api-with-the-help-of-ai/ https://blogs.perficient.com/2026/01/13/from-legacy-to-modern-migrating-wcf-to-web-api-with-the-help-of-ai/#respond Tue, 13 Jan 2026 17:32:36 +0000 https://blogs.perficient.com/?p=389673

Introduction

The modernization of legacy applications has always been a costly process: understanding old code, uncovering hidden dependencies, translating communication models (for example, from SOAP to REST), and ensuring that nothing breaks in production. This is where artificial intelligence changes the game.

AI does not replace the architect or the developer, but it speeds up the heaviest steps in a migration: it helps read and summarize large codebases, proposes equivalent designs in the new technology, generates drafts of controllers, DTOs, and tests, and even suggests architectural improvements that take advantage of the change. Instead of spending hours on mechanical tasks, the team can focus on what really matters: the business rules and the quality of the new solution.

In this post, we’ll look at that impact applied to a concrete case: migrating a WCF service written in C# to an ASP.NET Core Web API, using a real public repository as a starting point and relying on AI throughout the entire process.

Sample project: a real WCF service to be migrated

For this article, we’ll use the public project jecamayo/t-facturo.net as a real-world example: a .NET application that exposes SOAP services based on WCF to manage advisors and branches, using NHibernate for data access. This kind of solution perfectly represents the scenario of many legacy applications currently running in production, and it will serve as our basis to show how artificial intelligence can speed up and improve their migration to a modern architecture with ASP.NET Core Web API.

Key Steps to Migrate from Legacy WCF to a Modern Web API

Migrating a legacy application is not just about “moving code” from one technology to another: it involves understanding the business context, the existing architecture, and designing a modern solution that will be sustainable over time. To structure that process—and to clearly show where artificial intelligence brings the most value—it’s useful to break the migration down into a few key steps like the ones we’ll look at next.

  1. Define the goals and scope of the migration
    Clarify what you want to achieve with the modernization (for example, moving to .NET 8, exposing REST, improving performance or security) and which parts of the system are in or out of the project, in order to avoid surprises and rework.
  2. Analyze the current architecture and design the target architecture
    Understand how the solution is built today (layers, projects, WCF, NHibernate, database) and, with that snapshot, define the target architecture in ASP.NET Core Web API (layers, patterns, technologies) that will replace the legacy system.
  3. Identify dependencies, models, DTOs, and business rules
    Locate external libraries, frameworks, and critical components; inventory domain entities and DTOs; and extract the business rules present in the code to ensure they are properly preserved in the new implementation.
  4. Design the testing strategy and migration plan
    Decide how you will verify that the new API behaves the same (unit tests, integration tests, comparison of WCF vs Web API responses) and define whether the migration will be gradual or a “big bang”, including phases and milestones.
  5. Implement the new Web API, validate it, and retire the legacy WCF
    Build the Web API following the target architecture, migrate the logic and data access, run the test plan to validate behavior, deploy the new solution and, once its stability has been confirmed, deactivate the inherited WCF service.

How to Use AI Prompts During a Migration

Artificial intelligence becomes truly useful in a migration when we know what to ask of it and how to ask it. It’s not just about “asking for code,” but about leveraging it in different phases: understanding the legacy system, designing the target architecture, generating repetitive parts, proposing tests, and helping document the change. To do this, we can classify prompts into a few simple categories (analysis, design, code generation, testing, and documentation) and use them as a practical guide throughout the entire migration process.

Analysis and Understanding Prompts

These focus on having the AI read the legacy code and help you understand it faster: what a WCF service does, what responsibilities a class has, how projects are related, or which entities and DTOs exist. They are ideal for obtaining “mental maps” of the system without having to review every file by hand.

Usage examples:

  • Summarize what a project or a WCF service does.
  • Explain what responsibilities a class or layer has.
  • Identify domain models, DTOs, or design patterns.

Design and Architecture Prompts

These are used to ask the AI for target architecture proposals in the new technology: how to translate WCF contracts into REST endpoints, what layering structure to follow in ASP.NET Core, or which patterns to apply to better separate domain, application, and infrastructure. They do not replace the architect’s judgment, but they offer good starting points and alternatives.

Usage examples:

  • Propose how to translate a WCF contract into REST endpoints.
  • Suggest a project structure following Clean Architecture.
  • Compare technological alternatives (keeping NHibernate vs migrating to EF Core).

Code Generation and Refactoring Prompts

These are aimed at producing or transforming specific code: generating Web API controllers from WCF interfaces, creating DTOs and mappings, or refactoring large classes into smaller, more testable services. They speed up the creation of boilerplate and make it easier to apply good design practices.

Usage examples:

  • Create a Web API controller from a WCF interface.
  • Generate DTOs and mappings between entities and response models.
  • Refactor a class with too many responsibilities into cleaner services/repositories.

Testing and Validation Prompts

Their goal is to help ensure that the migration does not break existing behavior. They can be used to generate unit and integration tests, define representative test cases, or suggest ways to compare responses between the original WCF service and the new Web API.

Usage examples:

  • Generate unit or integration tests for specific endpoints.
  • Propose test scenarios for a business rule.
  • Suggest strategies to compare responses between WCF and Web API.

Documentation and Communication Prompts

They help explain the before and after of the migration: documenting REST endpoints, generating technical summaries for the team, creating tables that show the equivalence between WCF operations and Web API endpoints, or writing design notes for future evolutions. They simplify communication with developers and non-technical stakeholders.

Usage examples:

  • Write documentation for the new API based on the controllers.
  • Generate technical summaries for the team or stakeholders.
  • Create equivalence tables between WCF operations and REST endpoints.

To avoid making this article too long and to be able to go deeper into each stage of the migration, we’ll leave the definition of specific prompts —with real examples applied to the t-facturo.net project— for an upcoming post. In that next article, we’ll go through, step by step, what to ask the AI in each phase (analysis, design, code generation, testing, and documentation) and how those prompts directly impact the quality, speed, and risk of a WCF-to-Web-API migration.

Conclusions

The experience of migrating a legacy application with the help of AI shows that its main value is not just in “writing code,” but in reducing the intellectual friction of the process: understanding old systems, visualizing possible architectures, and automating repetitive tasks. Instead of spending hours reading WCF contracts, service classes, and DAOs, AI can summarize, classify, and propose migration paths, allowing the architect and the team to focus their time on key design decisions and business rules.

At the same time, AI speeds up the creation of the new solution: it generates skeletons for Web API controllers, DTOs, mappings, and tests, acting as an assistant that produces drafts for the team to iterate on and improve. However, human judgment remains essential to validate each proposal, adapt the architecture to the organization’s real context, and ensure that the new application not only “works,” but is maintainable, secure, and aligned with business goals.

]]>
https://blogs.perficient.com/2026/01/13/from-legacy-to-modern-migrating-wcf-to-web-api-with-the-help-of-ai/feed/ 0 389673
Model Context Protocol (MCP) – Simplified https://blogs.perficient.com/2026/01/08/model-context-protocol-mcp-simplified/ https://blogs.perficient.com/2026/01/08/model-context-protocol-mcp-simplified/#comments Thu, 08 Jan 2026 07:50:15 +0000 https://blogs.perficient.com/?p=389415

What is MCP?

Model Context Protocol (MCP) is an open-source standard for integrating AI applications to external systems. With AI use cases getting traction more and more, it becomes evident that AI applications tend to connect to multiple data sources to provide intelligent and relevant responses.

Earlier AI systems interacted with users through Large language Models (LLM) that leveraged pre-trained datasets. Then, in larger organizations, business users work with AI applications/agents expect more relevant responses from enterprise dataset, from where Retrieval Augmented Generation (RAG) came into play.

Now, AI applications/agents are expected to produce more accurate responses leveraging latest data, that requires AI systems to interact with multiple data sources and fetch accurate information. When multi-system interactions are established, it requires the communication protocol to be more standardized and scalable. That is where MCP enables a standardized way to connect AI applications to external systems.

 

Architecture

Mcp Architecture

Using MCP, AI applications can connect to data source (ex; local files, databases), tools and workflows – enabling them to access key information and perform tasks. In enterprises scenario, AI applications/agents can connect to multiple databases across organization, empowering users to analyze data using natural language chat.

Benefits of MCP

MCP serves a wide range of benefits

  • Development: MCP reduces development time and complexity when building, or integrating with AI application/agent. It makes integrating MCP host with multiple MCP servers simple by leveraging built-in capability discovery feature.
  • AI applications or agents: MCP provides access to an ecosystem of data sources, tools and apps which will enhance capabilities and improve the end-user experience.
  • End-users: MCP results in more capable AI applications or agents which can access your data and take actions on user behalf when necessary.

MCP – Concepts

At the top level of MCP concepts, there are three entities,

  • Participants
  • Layers
  • Data Layer Protocol

 

Participants

MCP follows a client-server architecture where an MCP host – an AI application like enterprise chatbot establishes connections to one or more MCP servers. The MCP host accomplishes this by creating a MCP client for each MCP server. Each MCP client maintains a dedicated connection with its MCP server.

The key participants of MCP architecture are:

  • MCP Host: AI application that coordinates and manages one or more MCP clients
  • MCP Client: A component that maintains a dedicated connection to an MCP server and obtains context from an MCP server for MCP host to interact
  • MCP Server: A program that provides context to MCP clients (i.e. generate responses or perform actions on user behalf)

Mcp Client Server

Layers

MCP consists of two layers:

  • Data layer – Defines JSON-RPC based protocol for client-server communication including,
    • lifecycle management – initiate connection, capability discovery & negotiation, connection termination
    • Core primitives – enabling server features like tools for AI actions, resources for context data, prompt templates for client-server interaction and client features like ask client to sample from host LLM, log messages to client
    • Utility features – Additional capabilities like real-time notifications, track progress for long-running operations
  • Transport Layer – Manages communication channels and authentication between clients and servers. It handles connection establishment, message framing and secure communication between MCP participants

Data Layer Protocol

The core part of MCP is defining the schema and semantics between MCP clients and MCP servers. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.

MCP uses JSON-RPC 2.0 as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.

Life Cycle Management

MCP is a stateful protocol that requires lifecycle management. The purpose of lifecycle management is to negotiate the capabilities (i.e. functionalities) that both client and server support.

Primitives

Primitives define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed. MCP defines three core primitives that servers can expose:

  • Tools: Executable functions that AI applications can invoke to perform actions (e.g., API calls, database queries)
  • Resources: Data sources that provide contextual information to AI applications (e.g., file contents, API responses, database records)
  • Prompts: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)

 

Notifications

The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server’s available tools change – such as when new functionalities are added or existing functionality is updated – the server can send tool update notifications to all its connected clients about these changes.

 

Security in Data Accessing

While AI applications communicate with multiple enterprise data sources thgrouch MCP and fetch real-time sensitive data like customer information, financial data to serve the users, data security becomes absolutely critical factor to be addressed.

MCP ensures secure access.

Authentication and Authorization

MCP implements server-side authentication where each MCP server validates who is making the request. The enterprise system controls access through:

  • User-specific credentials – Each user connecting through MCP has their own authentication tokens
  • Role-based access control (RBAC) – Users only access data that the role permits
  • Session management – Time-limited sessions that expire automatically

Data Access Controls

MCP server acts as a security gateway that enforces the same access policies as direct system access:

    • Users can only query data that they are authroized to access
    • The server validates every request against permission rules
    • Sensitive information can be masked or filtered based on user privileges

Secure Communication

      • Encrypted connections – All data transmissions uses TLS/HTTPS encryption
      • No data storage in AI – AI systems do not store the financial data it accesses; it only process it during the conversation session

Audit and Monitoring

MCP implementations in enterprise ecosystem should include:

      • Complete audit logs – Every data access request is logged with user, timestamp and data accessed
      • Anomaly detection – Engage mechanisms that monitor unusual access patterns and trigger alerts
      • Compliance tracking – All interactions meet regulatory requirements like GDPR, PCI-DSS

Architecture Isolation

Enterprises typically deploy MCP using:

      • Private network deployment – MCP servers stay within the enterprise secure firewall boundary
      • API gateway integration – Requests go through existing security infrastructure
      • No direct database access – MCP connects and access data through secure APIs, not direct access to database

The main idea is that MCP does not bypass existing security. It works within the same security as other enterprise applications, just showing a smarter interface.

 

MCP Implementation & Demonstration

In this section, I will demonstrate a simple use case where MCP client (Claude Desktop) interacts with “Finance Manager” MCP server that can fetch financial information from the database.

Financial data is maintained in Postgres database tables. MCP client (Claude Desktop app) will request information about customer account, MCP host will discover appropriate capability based on user prompt and invoke respective MCP tool function that can fetch data from the database table.

To make MCP client-server in action, there are three parts to be configured

      • Backend Database
      • MCP server implementation
      • MCP server registration in MCP Host

Backend Database

Postgres table “accounts” maintains accounts data with below information, “transactions” table maintains the transaction performed on the accounts

Accounts Table

Transactions Table

MCP server implementation

Mcp Server Implementation

FastMCP class implements MCP server components and creating an object of it initialize and enables access to those components to create enterprise MCP server capabilities.

The annotation “@mcp.tool()” defines the capability and the respective function will be recognized as MCP capability. These functions will be exposed to AI applications and will be invoked from MCP Host to perform designated actions.

In order to invoke MCP capabilities from client, MCP server should be up & running. In this example, there are two functions defined as MCP tool capabilities,

      • get_account_details – The function accept account number as input parameter, query “accounts” table and returns account information
      • add_transaction – The function accepts account number and transaction amount as parameters, make entry into “transactions” table

 

MCP Server Registration in MCP Host

For AI applications to invoke MCP server capability, MCP server should be registered in MCP host at client end. For this demonstration, I am using Claude Desktop as MCP client from where I interact with MCP server.

First, MCP server is registered with MCP host in Claude Desktop as below,

Claude Desktop -> Settings -> Developer -> Local MCP Servers -> Click “Edit Config”

Developer Settings

Open “claude_desktop_config” JSON file in Notepad. Add configurations in the JSON as below. The configurations define the path where MCP server implementation is located and instruct command to MCP host to run. Save the file and close.

Register Mcp Server

Restart “Claude Desktop” application, go to Settings -> Developer -> Local MCP servers tab. The newly added MCP server (finance-manager) will be in running state as below,

Mcp Server Running

Go to chat window in Claude Desktop. Issue a prompt to fetch details of an account in “accounts” table and review the response,

 

Claude Mcp Invocation

User Prompt: User issues a prompt to fetch details of an account.

MCP Discovery & Invoke: The client (Claude Desktop) processes the prompt, interacts with MCP host, automatically discover the relevant capability – get_account_details function in this case – without explicitly mention the function name and invoke the function with necessary parameter.

Response: MCP server process the request, fetch account details from the table and respond details to the client. The client formats the response and present it to the user.

Another example to add a transaction in the backend table for an account,

Mcp Server Add Transaction

Here, “add_transaction” capability has been invoked to add a transaction record in “transactions” table. In the chat window, you could notice that what MCP function is being invoked along with request & response body.

The record has been successfully added into the table,

Add Transaction Postgres Table

Impressive, isn’t it..!!

There are a wide range of use cases implementing MCP servers and integrate with enterprise AI systems that bring in intelligent layer to interact with enterprise data sources.

Here, you may also develop a thought that in what ways MCP (Model Context Protocol) is different from RAG (Retrieval Augmented Generation), as I did so. Based on my research, I just curated a comparison matrix of the features that would add more clarity,

 

Aspect RAG (Retrieval Augmented Generation) MCP (Model Context Protocol)
Purpose Retrieve unstructured docs to improve LLM responses AI agents access structured data/tools dynamically
Data Type Unstructured text (PDFs, docs, web pages) Structured data (JSON, APIs, databases)
Workflow Retrieve → Embed → Prompt injection → Generate AI requests context → Protocol delivers → AI reasons
Context Delivery Text chunks stuffed into prompt Structured objects via standardized interface
Token Usage High (full text in context) Low (references/structured data)
Action Capability Read-only (information retrieval) Read + Write (tools, APIs, actions)
Discovery Pre-indexed vector search Runtime tool/capability discovery
Latency Retrieval + embedding time Real-time protocol calls
Use Case Q&A over documents, chatbots AI agents, tool calling, enterprise systems
Maturity Widely adopted, mature ecosystem Emerging standard (2025+)
Complexity Vector DB + embedding pipeline Protocol implementation + AI agent

 

Conclusion

MCP Servers extend the capabilities of AI assistants by allowing them to interact with external services and data sources using natural language commands. Model Context Protocol (MCP) has a wide range of use cases and there are several enterprises already implemented and hosted MCP servers for AI clients to integrate and interact.

Some of the prominent MCP servers include:

GitHub MCP Server: Allows AI to manage repositories, issues, pull requests, and monitor CI/CD workflows directly within the development environment.

Azure DevOps MCP Server: Integrates AI with Azure DevOps services for managing pipelines, work items and repositories, ideal for teams withing the Microsoft ecosystem.

PostgreSQL MCP Server: bridges the gap between AI and databases, allowing natural language queries, schema exploration and data analysis without manual SQL scripting.

Slack MCP Server: Turns Slack into an AI-powered collaboration hub, enabling message posting, channel management

]]>
https://blogs.perficient.com/2026/01/08/model-context-protocol-mcp-simplified/feed/ 1 389415
Microservices: The Emerging Complexity Driven by Trends and Alternatives to Over‑Design https://blogs.perficient.com/2025/12/31/microservices-the-emerging-complexity-driven-by-trends-and-alternatives-to-over-design/ https://blogs.perficient.com/2025/12/31/microservices-the-emerging-complexity-driven-by-trends-and-alternatives-to-over-design/#respond Wed, 31 Dec 2025 15:13:56 +0000 https://blogs.perficient.com/?p=389360

The adoption of microservice‑based architectures has grown exponentially over the past decade, often driven more by industry trends than by a careful evaluation of system requirements. This phenomenon has generated unnecessarily complex implementations—like using a bazooka to kill an ant. Distributed architectures without solid foundations in domain capabilities, workloads, operational independence, or real scalability needs have become a common pattern in the software industry. In many cases, organizations migrate without having a mature discipline in observability, traceability, automation, domain‑driven design, or an operational model capable of supporting highly distributed systems; as a consequence, they end up with distributed monoliths that require coordinated deployments and suffer cascading failures, losing the benefits originally promised by microservices (Iyer, 2025; Fröller, 2025).

Over‑Design

The primary issue in microservices is not rooted in their architectural essence, but in the over‑design that emerges when attempting to implement such architecture without having a clear roadmap of the application’s domains or of the contextual boundaries imposed by business rules. The decomposition produces highly granular, entity‑oriented services that often result in circular dependencies, duplicated business logic, excessive events without meaningful semantics, and distributed flows that are difficult to debug. Instead of achieving autonomy and independent scalability, organizations create a distributed monolith with operational complexity multiplied by the number of deployed services. A practical criterion to avoid this outcome is to postpone decomposition until stable boundaries and non‑functional requirements are fully understood, even adopting a monolith‑first approach before splitting (Fowler, 2015; Danielyan, 2025).

Minimal API and Modular Monolith as Alternatives to Reduce Complexity

In these scenarios, it is essential to explore alternatives that allow companies to design simpler microservices without sacrificing architectural clarity or separation of concerns. One such alternative is the use of Minimal APIs to reduce complexity in the presentation layer: this approach removes ceremony (controllers, conventions, annotations) and accelerates startup while reducing container footprint. It is especially useful for utility services, CRUD operations, and limited API surfaces (Anderson & Dykstra, 2024; Chauhan, 2024; Nag, 2025).

Another effective alternative is the Modular Monolith. A well‑modularized monolith enables isolating functional domains within internal modules that have clear boundaries and controlled interaction rules, simplifying deployment, reducing internal latency, and avoiding the explosion of operational complexity. Additionally, it facilitates a gradual migration toward microservices only when objective reasons exist (differentiated scaling needs, dedicated teams, different paces of domain evolution) (Bächler, 2025; Bauer, n.d.).

Improving the API Gateway and the Use of Event‑Driven Architectures (EDA)

The API Gateway is another critical component for managing external complexity: it centralizes security policies, versioning, rate limiting, and response transformation/aggregation, hiding internal topology and reducing client cognitive load. Patterns such as Backend‑for‑Frontend (BFF) and aggregation help decrease network trips and prevent each public service from duplicating cross‑cutting concerns (Microsoft, n.d.-b; AST Consulting, 2025).

A key principle for reducing complexity is to avoid decomposition by entities and instead guide service boundaries using business capabilities and bounded contexts. Domain‑Driven Design (DDD) provides a methodological compass to define coherent semantic boundaries; mapping bounded contexts to services (not necessarily in a 1:1 manner) reduces implicit coupling, prevents domain model ambiguity, and clarifies service responsibilities (Microsoft, n.d.-a; Polishchuk, 2025).

Finally, the use of Event‑Driven Architectures (EDA) should be applied judiciously. Although EDA enhances scalability and decoupling, poor implementation significantly increases debugging effort, introduces hidden dependencies, and complicates traceability. Mitigating these risks requires discipline in event design/versioning, the outbox pattern, idempotency, and robust telemetry (correlation IDs, DLQs), in addition to evaluating when orchestration (Sagas) is more appropriate than choreography (Three Dots Labs, n.d.; Moukbel, 2025).

Conclusion

The complexity associated with microservices arises not from the architecture itself, but from misguided adoption driven by trends. The key to reducing this complexity is prioritizing cohesion, clarity, and gradual evolution: Minimal APIs for small services, a Modular Monolith as a solid foundation, decomposition by real business capabilities and bounded contexts, a well‑defined gateway, and a responsible approach to events. Under these principles, microservices stop being a trend and become an architectural mechanism that delivers real value (Fowler, 2015; Anderson & Dykstra, 2024).

References

  • Anderson, R., & Dykstra, T. (2024, julio 29). Tutorial: Create a Minimal API with ASP.NET Core. Microsoft Learn. https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-10.0
  • AST Consulting. (2025, junio 12). API Gateway in Microservices: Top 5 Patterns and Best Practices Guide. https://astconsulting.in/microservices/api-gateway-in-microservices-patterns
  • Bächler, S. (2025, enero 23). Modular Monolith: The Better Alternative to Microservices. ti&m. https://www.ti8m.com/en/blog/monolith
  • Bauer, R. A. (s. f.). On Modular Monoliths. https://www.raphaelbauer.com/posts/on-modular-monoliths/
  • Danielyan, M. (2025, febrero 4). When to Choose Monolith Over Microservices. https://mikadanielyan.com/blog/when-to-choose-monolith-over-microservices
  • Fowler, M. (2015, junio 3). Monolith First. https://martinfowler.com/bliki/MonolithFirst.html
  • Fröller, J. (2025, octubre 30). Many Microservice Architectures Are Just Distributed Monoliths. MerginIT Blog. https://merginit.com/blog/31102025-microservices-antipattern-distributed-monolit
  • Iyer, A. (2025, junio 3). Why 90% of Microservices Still Ship Like Monoliths. The New Stack. https://thenewstack.io/why-90-of-microservices-still-ship-like-monoliths/
  • Microsoft. (s. f.-a). Domain analysis for microservices. Azure Architecture Center. https://learn.microsoft.com/en-us/azure/architecture/microservices/model/domain-analysis
  • Microsoft. (s. f.-b). API gateways. Azure Architecture Center. https://learn.microsoft.com/en-us/azure/architecture/microservices/design/gateway
  • Moukbel, T. (2025). Event-Driven Architecture: Pitfalls and Best Practices. Undercode Testing. https://undercodetesting.com/event-driven-architecture-pitfalls-and-best-practices/
  • Nag, A. (2025, julio 29). Why Minimal APIs in .NET 8 Are Perfect for Microservices Architecture?. embarkingonvoyage.com. https://embarkingonvoyage.com/blog/technologies/why-minimal-apis-in-net-8-are-perfect-for-microservices-architecture/
  • Polishchuk. (2025, diciembre 12). Design Microservices: Using DDD Bounded Contexts. bool.dev. https://bool.dev/blog/detail/ddd-bounded-contexts
  • Three Dots Labs. (s. f.). Event-Driven Architecture: The Hard Parts. https://threedots.tech/episode/event-driven-architecture/
  • Chauhan, P. (2024, septiembre 30). Deep Dive into Minimal APIs in ASP.NET Core 8. https://www.prafulchauhan.com/blogs/deep-dive-into-minimal-apis-in-asp-net-core-8
]]>
https://blogs.perficient.com/2025/12/31/microservices-the-emerging-complexity-driven-by-trends-and-alternatives-to-over-design/feed/ 0 389360
Beyond the Version Bump: Lessons from Upgrading React Native 0.72.7 → 0.82 https://blogs.perficient.com/2025/12/24/beyond-the-version-bump-lessons-from-upgrading-react-native-0-72-7-%e2%86%92-0-82/ https://blogs.perficient.com/2025/12/24/beyond-the-version-bump-lessons-from-upgrading-react-native-0-72-7-%e2%86%92-0-82/#respond Wed, 24 Dec 2025 08:39:47 +0000 https://blogs.perficient.com/?p=389288

Introduction

When I started investigating the React Native upgrade from 0.72.7 to 0.82, my initial goal was simple:  

Check breaking changes and library compatibility. But very quickly, I realized this upgrade was not just a version bump. It was deeply tied to React Native’s New Architecture, especially Fabric UI Engine and TurboModules.  This blog shares what I discovered, what changed internally, and why this upgrade matters in real-world apps, not just release notes. 

Why I Started Digging Deeper  

At first glance:  

  • The app was already stable 
  • Performance was “acceptable” 
  • Most screens worked fine

Why should we even care about Fabric and TurboModules while upgrading?

The answer became clear when I compared how React Native worked internally in 0.72.7 vs 0.82. 

The Reality in React Native 0.72.7 (Old Architecture) 

In 0.72.7, even though the New Architecture existed, most apps were still effectively running on the old bridge model. 

What I Observed 

  • UI updates were asynchronous 
  • JS → Native communication relied on serialized messages 
  • Native modules were eagerly loaded 
  • Startup time increased as the app grew 

Performance issues appeared under: 

  • Heavy animations 
  • Large FlatLists 
  • Complex navigation stacks 

None of these were “bugs” they were architectural limitations. 

What Changed in React Native 0.82 

Screenshot 2025 12 23 At 3.51.45 pm

Screenshot 2025 12 23 At 3.52.03 pm

Screenshot 2025 12 23 At 3.52.38 pm

By the time I reached 0.82, it was clear that Fabric and TurboModules were no longer optional concepts they were becoming the default future. The upgrade forced me to understand why React Native was redesigned internally. 

My Understanding of Fabric UI Engine (After Investigation) 

Fabric is not just a rendering upgrade it fundamentally changes how UI updates happen. 

What Changed Compared to 0.72.7

Synchronous UI Updates

Earlier: 

  • UI updates waited for the JS bridge 

With Fabric: 

  • UI updates can happen synchronously 
  • JS and Native talk directly through JSI 
  • Result: noticeably smoother interactions 

This became obvious in: 

  • Gesture-heavy screens 
  • Navigation transitions 
  • Scroll performance 

Shared C++ Core

While upgrading, I noticed Fabric uses a shared C++ layer between: 

  • JavaScript 
  • iOS 
  • Android 

This reduces: 

  • Data duplication 
  • Platform inconsistencies 
  • Edge-case UI bugs 

From a maintenance point of view, this is huge. 

Better Support for Concurrent Rendering

Fabric is built with modern React features in mind. 

That means: 

  • Rendering can be interrupted 
  • High-priority UI updates are not blocked 
  • Heavy JS work doesn’t freeze the UI 

In practical terms: 

The app feels more responsive, even when doing more. TurboModules: The Bigger Surprise for Me, I initially thought TurboModules were just an optimization. After digging into the upgrade docs and native code, I realized they solve multiple real pain points I had faced earlier. 

What I Faced in 0.72.7 

  • All native modules are loaded at startup 
  • App launch time increased as features grew 
  • Debugging JS ↔ Native mismatches was painful 
  • Weak type safety caused runtime crashes 

What TurboModules Changed:

Lazy Loading by Default

With TurboModules: 

  • Native modules load only when accessed 
  • Startup time improves automatically 
  • Memory usage drops 

This alone makes a big difference in large apps. 

Direct JS ↔ Native Calls (No Bridge)

TurboModules use JSI instead of the old bridge. 

That means: 

  • No JSON serialization 
  • No async message queue 
  • Direct function calls 

From a performance perspective, this is a game-changer. 

Stronger Type Safety

Using codegen, the interface between JS and Native becomes: 

  • Explicit 
  • Predictable 
  • Compile-time safe 

Fabric + TurboModules Together (The Real Upgrade) 

What I realized during this migration is: 

Fabric and TurboModules don’t shine individually they shine together.  

Area   React Native 0.72.7   React Native 0.82  
UI Rendering   Async bridge   Synchronous (Fabric)  
Native Calls   Serialized   Direct (JSI)  
Startup Time   Slower   Faster  
Animations   Jank under load   Smooth  
Native Integration   Fragile   Strong & typed  
Scalability   Limited   Production-ready  

My Final Take After the Upgrade Investigation 

Upgrading from 0.72.7 to 0.82 made one thing very clear to me: 

This is not about chasing versions. This is about adopting a new foundation. 

 Fabric and TurboModules: 

  • Remove long-standing architectural bottlenecks 
  • Make React Native feel closer to truly native apps 
  • Prepare apps for future React features 
  • Reduce hidden performance debt 

If someone asks me now: 

“Is the New Architecture worth it?” 

My answer is simple: 

If you care about performance, scalability, and long-term maintenance yes, absolutely. 

]]>
https://blogs.perficient.com/2025/12/24/beyond-the-version-bump-lessons-from-upgrading-react-native-0-72-7-%e2%86%92-0-82/feed/ 0 389288
Bulgaria’s 2026 Euro Adoption: What the End of the Lev Means for Markets https://blogs.perficient.com/2025/12/22/bulgarias-2026-euro-adoption-what-the-end-of-the-lev-means-for-markets/ https://blogs.perficient.com/2025/12/22/bulgarias-2026-euro-adoption-what-the-end-of-the-lev-means-for-markets/#comments Mon, 22 Dec 2025 17:03:29 +0000 https://blogs.perficient.com/?p=389245

Moments of currency change are where fortunes are made and lost. In January 2026, Bulgaria will enter one of those moments. The country will adopt the euro and officially retire the Bulgarian lev, marking a major euro adoption milestone and reshaping how investors, banks, and global firms manage currency risk in the region. The shift represents one of the most significant macroeconomic transitions in Bulgaria’s modern history and is already drawing attention across FX markets.

To understand how dramatically foreign exchange movements can shift value, consider one of the most famous examples in modern financial history. In September 1992, investor George Soros, “the man who broke the British Bank,” bet against the British pound, anticipating that the UK’s exchange rate policy would collapse. The resulting exchange rate crisis, now known as Black Wednesday, became a defining moment in forex trading and demonstrated how quickly policy decisions can trigger massive market dislocations.

By selling roughly $10 billion worth of pounds, his Quantum Fund earned ~$1 billion in profit when the currency was forced to devalue. The trade earned Soros the nickname “the man who broke the Bank of England” and remains a lasting example of how quickly confidence and capital flows can move entire currency systems.

Screenshot 2025 12 22 At 11.43.20 am

GBP/USD exchange rate from May 1992 to April 1993, highlighting the dramatic plunge during Black Wednesday. When George Soros famously shorted the pound, forcing the UK out of the ERM and triggering one of the most significant currency crises in modern history

To be clear, Bulgaria is not in crisis. The Soros example simply underscores how consequential currency decisions can be. Even when they unfold calmly and by design, currency transitions reshape the texture of daily life. The significance of Bulgaria’s transition becomes more clear when you consider what the lev has long represented. Safety. Families relied on it through political uncertainty and economic swings, saved it for holidays, passed it down during milestones, and trusted it in moments when little else felt predictable. Over time, the lev became a source of stability as Bulgaria navigated decades of change and gradually aligned itself with the European Union..

Its retirement feels both symbolic and historic. But for global markets, currency traders, banks, and companies engaged in cross border business, the transition is not just symbolic. It introduces real operational changes that require early attention. This article explains what is happening, why it matters, and how organizations can prepare.

Some quick facts help frame the scale of this shift.

Screenshot 2025 12 22 At 11.34.43 am

Map of Bulgaria

Bulgaria has a population of roughly 6.5 million.

The country’s GDP is about 90 billion U.S. dollars (World Bank, 2024)

Its largest trade partners are EU member states, Turkey, and China.

Why Bulgaria Is Adopting the Euro

​​Although the move from the Lev to the Euro is monumental, many Bulgarians also see it as a natural progression. ​​When Bulgaria joined the European Union in 2007, Euro adoption was always part of the long-term plan. Adopting the Euro gives Bulgaria a stronger foundation for investment, more predictable trade relationships, and smoother participation in Europe’s financial systems. It is the natural next step in a journey the country has been moving toward slowly, intentionally, and with growing confidence. That measured approach fostered public and institutional trust, leading European authorities to approve Bulgaria’s entry into the Eurozone on January 1, 2026 (European Commission, 2023; European Central Bank, 2023).

How Euro Adoption Affects Currency Markets

Bulgaria’s economy includes manufacturing, agriculture, energy, and service sectors. Its exports include refined petroleum, machinery, copper products, and apparel. It imports machinery, fuels, vehicles, and pharmaceuticals (OECD, 2024). The Euro supports smoother trade relationships within these sectors and reduces barriers for European partners.

Once Bulgaria switches to the Euro, the Lev will quietly disappear from global currency screens. Traders will no longer see familiar pairs like USD to BGN or GBP to BGN. Anything involving Bulgaria will now flow through euro-based pairs instead. In practical terms, the Lev simply stops being part of the conversation.

For people working on trading desks or in treasury teams, this creates a shift in how risk is measured day to day. Hedging strategies built around the Lev will transition to euro-based approaches. Models that once accounted for Lev-specific volatility will have to be rewritten. Automated trading programs that reference BGN pricing will need to be updated or retired. Even the market data providers that feed information into these systems will phase out Lev pricing entirely.

And while Bulgaria may be a smaller player in the global economy, the retirement of a national currency is never insignificant. It ripples through the internal workings of trading floors, risk management teams, and the systems that support them . It is a reminder that even quiet changes in one part of the world can require thoughtful adjustments across the financial landscape.

Combined with industry standard year-end code-freezes, Perficient has seen and helped clients stop their Lev trading weeks before year-end.

The Infrastructure Work Behind Adopting the Euro

Adopting the Euro is not just a change people feel sentimental about. Behind the scenes, it touches almost every system that moves money. Every financial institution uses internal currency tables to keep track of existing currencies, conversion rules, and payment routing. When a currency is retired, every system that touches money must be updated to reflect the change.

This includes:

  • Core banking and treasury platforms
  • Trading systems
  • Accounting and ERP software
  • Payment networks, including SWIFT and ISO 20022
  • Internal data warehouses and regulatory reporting systems

Why Global Firms Should Pay Attention

If the Lev remains active anywhere after the transition, payments can fail, transactions can be misrouted, and reconciliation issues can occur. The Bank for International Settlements notes that currency changes require “significant operational coordination,” because risk moves across systems faster than many institutions expect. 

Beyond the technical updates, the disappearance of the Lev also carries strategic implications for multinational firms. Any organization that operates across borders, whether through supply chains, treasury centers, or shared service hubs, relies on consistent currency identifiers to keep financial data aligned. If even one system, vendor, or regional partner continues using the old code, firms can face cascading issues such as misaligned ledgers, failed hedging positions, delayed settlements, and compliance flags triggered by mismatched reporting. In a world where financial operations are deeply interconnected, a seemingly local currency change can ripple outward and affect global liquidity management and operational continuity.

Many firms have already started their transition work well in advance of the official date in order to minimize risk. In practice, this means reviewing currency tables, updating payment logic, testing cross-border workflows, and making sure SWIFT and ISO 20022 messages recognize the new structure. 

Trade Finance Will Feel the Change

For people working in finance, this shift will change the work they do every day. Tools like Letters of Credit and Banker’s Acceptances are the mechanisms that keep international trade moving, and they depend on accurate currency terms. If any of these agreements are written to settle in Lev, they will need to be updated before January 2026.

That means revising contracts, invoices, shipping documents, and long-term payment schedules. Preparing early gives exporters, importers, and the teams supporting them the chance to keep business running smoothly through the transition.

What Euro Adoption Means for Businesses

Switching to the Euro unlocks several practical benefits that go beyond finance departments.

  • Lower currency conversion costs
  • More consistent pricing for long-term agreements
  • Faster cross-border payments within the European Union
  • Improved financial reporting and reduced foreign exchange risk
  • Increased investor confidence in a more stable currency environment

Because so much of Bulgaria’s trade already occurs with Eurozone countries, using the Euro simplifies business operations and strengthens economic integration.

How Organizations Can Prepare

The most important steps for institutions include:

  1. Auditing systems and documents for references to BGN
  2. Updating currency tables and payment rules
  3. Revising Letters of Credit and other agreements that list the Lev
  4. Communicating the transition timeline to partners and clients
  5. Testing updated systems well before January 1, 2026

Early preparation ensures a smooth transition when Bulgaria officially adopts the Euro. Ensure that operationally you’re prepared to accept Lev payments through December 31, 2025, but given settlement timeframes, prepared to reconcile and settle Lev transactions into 2026.a

Final Thoughts

The Bulgarian Lev has accompanied the country through a century of profound change. Its retirement marks the end of an era and the beginning of a new chapter in Bulgaria’s economic story. For the global financial community, Bulgaria’s adoption of the Euro is not only symbolic but operationally significant.

Handled thoughtfully, the transition strengthens financial infrastructure, reduces friction in global business, and supports a more unified European economy.

References 

Bank for International Settlements. (2024). Foreign exchange market developments and global liquidity trends. https://www.bis.org

Eichengreen, B. (1993). European monetary unification. Journal of Economic Literature, 31(3), 1321–1357.

European Central Bank. (2023). Convergence report. https://www.ecb.europa.eu

European Commission. (2023). Economic and monetary union: Euro adoption process. https://ec.europa.eu

Henriques, D. B. (2011). The billionaire was not always so bold. The New York Times.

Organisation for Economic Co-operation and Development. (2024). Economic surveys: Bulgaria. https://www.oecd.org

World Bank. (2024). Bulgaria: Country data and economic indicators. https://data.worldbank.org/country/bulgaria

 

]]>
https://blogs.perficient.com/2025/12/22/bulgarias-2026-euro-adoption-what-the-end-of-the-lev-means-for-markets/feed/ 1 389245
Lightning Web Security (LWS) in Salesforce https://blogs.perficient.com/2025/12/05/lightning-web-security-lws-in-salesforce/ https://blogs.perficient.com/2025/12/05/lightning-web-security-lws-in-salesforce/#respond Fri, 05 Dec 2025 06:51:04 +0000 https://blogs.perficient.com/?p=388406

What is Lightning Web Security?

Lightning Web Security (LWS) is Salesforce’s modern client-side security architecture designed to secure Lightning Web Components (LWC) and Aura components. Introduced as an improvement over the older Lightning Locker service, LWS enhances component isolation with better performance and compatibility with modern web standards.

Key Features of LWS

  • Namespace isolation: Each Lightning web component runs in its own JavaScript sandbox, preventing unauthorized access to data or code from other namespaces.

  • API distortion: LWS modifies standard JavaScript APIs dynamically to enforce security policies without breaking developer experience.

  • Supports third-party libraries: Unlike Locker, LWS allows broader use of community and open-source JS libraries.

  • Default in new orgs: Enabled by default for all new Salesforce orgs created from Winter ’23 release onwards.

Benefits of Using LWS

  • Stronger security: Limits cross-component and cross-namespace vulnerabilities.

  • Improved performance: Reduced overhead compared to Locker’s wrappers, resulting in faster load times for users.

  • Better developer experience: Easier to build robust apps without excessive security workarounds.

  • Compatibility: Uses the latest web standards and works well with modern browsers and tools.

How to Enable LWS in Your Org

  1. Navigate to Setup > Session Settings in Salesforce.

  2. Enable the checkbox for Use Lightning Web Security for Lightning web components and Aura components.

  3. Save settings and clear browser cache to ensure the change takes effect.

  4. Test your Lightning components thoroughly, ideally starting in a sandbox environment before deploying to production.

Best Practices for Working with LWS

  • Test extensively: Some existing components may require minor updates due to stricter isolation.

  • Use the LWS Console: Salesforce provides developer tools to inspect and debug components under LWS.

  • Follow secure coding guidelines: Maintain least privilege principle and avoid direct DOM manipulations.

  • Plan migration: Gradually transition from Lightning Locker to LWS, if upgrading older orgs.

  • Leverage Third-party Libraries Wisely: Confirm compatibility with LWS to avoid runtime errors.

Troubleshooting Common LWS Issues

  • Components failing due to namespace restrictions.

  • Unexpected behavior with third-party libraries.

  • Performance bottlenecks during initial page loading.

Utilize Salesforce’s diagnostic tools, logs, and community forums for support.

Resources for Further Learning

]]>
https://blogs.perficient.com/2025/12/05/lightning-web-security-lws-in-salesforce/feed/ 0 388406
Salesforce Marketing Cloud + AI: Transforming Digital Marketing in 2025 https://blogs.perficient.com/2025/12/05/salesforce-marketing-cloud-ai-transforming-digital-marketing-in-2025/ https://blogs.perficient.com/2025/12/05/salesforce-marketing-cloud-ai-transforming-digital-marketing-in-2025/#respond Fri, 05 Dec 2025 06:48:04 +0000 https://blogs.perficient.com/?p=388389

Salesforce Marketing Cloud + AI is revolutionizing marketing by combining advanced artificial intelligence with marketing automation to create hyper-personalized, data-driven campaigns that adapt in real time to customer behaviors and preferences. This fusion drives engagement, conversions, and revenue growth like never before.

Key AI Features of Salesforce Marketing Cloud

  • Agentforce: An autonomous AI agent that helps marketers create dynamic, scalable campaigns with effortless automation and real-time optimization. It streamlines content creation, segmentation, and journey management through simple prompts and AI insights. Learn more at the Salesforce official site.

  • Einstein AI: Powers predictive analytics, customized content generation, send-time optimization, and smart audience segmentation, ensuring the right message reaches the right customer at the optimal time.

  • Generative AI: Using Einstein GPT, marketers can automatically generate email copy, subject lines, images, and landing pages, enhancing productivity while maintaining brand consistency.

  • Marketing Cloud Personalization: Provides real-time behavioral data and AI-driven recommendations to deliver tailored experiences that boost customer loyalty and conversion rates.

  • Unified Data Cloud Integration: Seamlessly connects live customer data for dynamic segmentation and activation, eliminating data silos.

  • Multi-Channel Orchestration: Integrates deeply with platforms like WhatsApp, Slack, and LinkedIn to deliver personalized campaigns across all customer touchpoints.

Latest Trends & 2025 Updates

  • With advanced artificial intelligence, marketing teams benefit from systems that independently manage and adjust their campaigns for optimal results.

  • Real-time customer journey adaptations powered by live data.

  • Enhanced collaboration via AI integration with Slack and other platforms.

  • Automated paid media optimization and budget control with minimal manual intervention.

For detailed insights on AI and marketing automation trends, see this industry report.

Benefits of Combining Salesforce Marketing Cloud + AI

  • Increased campaign efficiency and ROI through automation and predictive analytics.

  • Hyper-personalized customer engagement at scale.

  • Reduced manual effort with AI-assisted content and segmentation.

  • Better decision-making powered by unified data and AI-driven insights.

  • Greater marketing agility and responsiveness in a changing landscape.

]]>
https://blogs.perficient.com/2025/12/05/salesforce-marketing-cloud-ai-transforming-digital-marketing-in-2025/feed/ 0 388389
Salesforce Custom Metadata getInstance vs SOQL: Key Differences & Best Practices. https://blogs.perficient.com/2025/12/05/salesforce-custom-metadata-getinstance-vs-soql/ https://blogs.perficient.com/2025/12/05/salesforce-custom-metadata-getinstance-vs-soql/#respond Fri, 05 Dec 2025 06:46:26 +0000 https://blogs.perficient.com/?p=377157

Salesforce provides powerful features to handle metadata, allowing you to store and access configuration data in a structured manner. In this blog, we explore Salesforce Custom Metadata getInstance vs SOQL—two key approaches developers use to retrieve custom metadata efficiently. Custom metadata types in Salesforce offer a great way to define reusable and customizable application data without worrying about governor limits that come with other storage solutions, like custom objects. For more details, you can visit the official Salesforce Trailhead Custom Metadata Types module. We will delve into the differences, use cases, and best practices for these two approaches.

What is Custom Metadata in Salesforce?

Custom metadata types are custom objects in Salesforce that store metadata or configuration data. Unlike standard or custom objects, they are intended for storing application configurations that don’t change often. These types are often used for things like:

  • Configuration settings for apps
  • Defining global values (like API keys)
  • Storing environment-specific configurations
  • Reusable data for automation or integrations

Custom metadata records can be easily managed via Setup, the Metadata API, or APEX.

Approach 1: Using getInstance()

getInstance() is a method that allows you to access a single record of a custom metadata type. It works on a “singleton” basis, meaning that it returns a specific instance of the custom metadata record.

How getInstance() Works

The getInstance() method is typically used when you’re looking to retrieve a single record of custom metadata in your code. This method is not intended to query multiple records or create complex filters. Instead, it retrieves a specific record directly, based on the provided developer name.

Example:

// Get a specific custom metadata record by its developer name
My_Custom_Metadata__mdt metadataRecord = My_Custom_Metadata__mdt.getInstance('My_Config_1');

// Access fields of the record
String configValue = metadataRecord.Config_Value__c;

When to Use getInstance()

  • Single Record Lookup: If you know the developer name of the record you’re looking for and expect to access only one record.
  • Performance: Since getInstance() is optimized for retrieving a single metadata record by its developer name, it can offer better performance than querying all records, especially when you only need one record.
  • Static Configuration: Ideal for use cases where the configuration is static, and you are sure that the metadata record will not change often.

Advantages of getInstance()

  • Efficiency: It’s quick and easy to retrieve a single metadata record when you already know the developer name.
  • Less Complex Code: This approach requires fewer lines of code and simplifies the logic, particularly in configuration-heavy applications.

Limitations of getInstance()

  • Single Record: It can only retrieve one record at a time.
  • No Dynamic Querying: It does not support complex filtering or dynamic querying like SOQL.

Approach 2: Using SOQL Queries

SOQL (Salesforce Object Query Language) is the standard way to retrieve multiple records in Salesforce, including custom metadata records. By using SOQL, you can query a custom metadata type much like any other object in Salesforce, providing flexibility in how records are retrieved.

How SOQL Queries Work

With SOQL, you can write queries that return multiple records, filter based on field values, or sort the records as needed. For instance:

// Query for multiple custom metadata records with SOQL
List<My_Custom_Metadata__mdt> metadataRecords = [SELECT MasterLabel, Config_Value__c FROM My_Custom_Metadata__mdt WHERE Active__c = TRUE];

// Loop through records and access their values
for (My_Custom_Metadata__mdt record : metadataRecords) {
    System.debug('Label: ' + record.MasterLabel + ', Value: ' + record.Config_Value__c);
}

When to Use SOQL Queries

  • Multiple Records: If you need to retrieve more than one record or apply filters to the query.
  • Dynamic Queries: When the records you’re querying are dynamic (e.g., based on user input or other logic).
  • Complex Criteria: If you need to use conditions like WHERE, ORDER BY, or join metadata with other objects.

Advantages of SOQL Queries

  • Flexibility: SOQL queries allow you to retrieve multiple records based on complex conditions.
  • Filtering and Sorting: You can easily filter and sort records to get the exact data you need.
  • Dynamic Usage: Ideal for cases where the data or records you’re querying may change, such as pulling all active configuration records.

Limitations of SOQL Queries

  • Governor Limits: SOQL queries are subject to Salesforce’s governor limits (e.g., the number of records returned and the number of queries per transaction).
  • Complexity: Writing and managing SOQL queries might introduce additional complexity in the code, especially when dealing with large datasets.

Key Differences: getInstance() vs. SOQL Queries

AspectgetInstance()SOQL Query
PurposeRetrieves a single record by developer nameRetrieves multiple records with flexibility
PerformanceFaster for a single record lookupSlower when retrieving many records
Use CaseStatic configuration data, single record lookupDynamic and multiple record retrieval
ComplexitySimple, minimal codeMore complex, requires query handling
Filtering & SortingNone, only by developer nameSupports filtering, sorting, and conditions
Governor LimitsDoesn't count against query limitsSubject to governor limits (e.g., 50,000 records per query)

Best Practices for Using getInstance() and SOQL

  • Use getInstance() when you need to access one specific metadata record and know the developer name beforehand. It’s efficient and optimized for simple lookups.
  • Use SOQL when you need to filter, sort, or access multiple metadata records. It’s more flexible and ideal for dynamic scenarios, but you should always be aware of governor limits to avoid hitting them.
  • Combine the Two: In some cases, you can use getInstance() for fetching critical single configuration records and SOQL for retrieving a list of configuration settings.

Conclusion

Both getInstance() and SOQL queries have their strengths when it comes to working with custom metadata types in Salesforce. Understanding when to use each will help optimize your code and ensure that your Salesforce applications run efficiently. For simple, static configurations, getInstance() is the way to go. For dynamic, large, or complex datasets, SOQL queries will offer the flexibility you need. By carefully selecting the right approach for your use case, you can harness the full power of Salesforce custom metadata.

]]>
https://blogs.perficient.com/2025/12/05/salesforce-custom-metadata-getinstance-vs-soql/feed/ 0 377157
Creators in Coding, Copycats in Class: The Double-Edged Sword of Artificial Intelligence https://blogs.perficient.com/2025/12/03/creators-in-coding-copycats-in-class-the-double-edged-sword-of-artificial-intelligence/ https://blogs.perficient.com/2025/12/03/creators-in-coding-copycats-in-class-the-double-edged-sword-of-artificial-intelligence/#respond Thu, 04 Dec 2025 00:30:15 +0000 https://blogs.perficient.com/?p=388808

“Powerful technologies require equally powerful ethical guidance.” (Bostrom, N. Superintelligence: Paths, Dangers, Strategies. Oxford University Press, 2014).

The ethics of using artificial intelligence depend on how we apply its capabilities—either to enhance learning or to prevent irresponsible practices that may compromise academic integrity. In this blog, I share reflections, experiences, and insights about the impact of AI in our environment, analyzing its role as a creative tool in the hands of developers and as a challenge within the academic context.

Between industry and the classroom

As a Senior Developer, my professional trajectory has led me to delve deeply into the fascinating discipline of software architecture. Currently, I work as a Backend Developer specializing in Microsoft technologies, facing daily the challenges of building robust, scalable, and well-structured systems in the business world.

Alongside my role in the industry, I am privileged to serve as a university professor, teaching four courses. Three of them are fundamental parts of the software development lifecycle: Software Analysis and Design, Software Architecture, and Programming Techniques. This dual perspective—as both a professional and a teacher—has allowed me to observe the rapid changes that technology is generating both in daily development practice and in the formation of future engineers.

Exploring AI as an Accelerator in Software Development

One of the greatest challenges for those studying the software development lifecycle is transforming ideas and diagrams into functional, well-structured projects. I always encourage my students to use Artificial Intelligence as a tool for acceleration, not as a substitute.

For example, in the Software Analysis and Design course, we demonstrate how a BPMN 2.0 process diagram can serve as a starting point for modeling a system. We also work with class diagrams that reflect compositions and various design patterns. AI can intervene in this process in several ways:

  • Code Generation from Models: With AI-based tools, it’s possible to automatically turn a well-built class diagram into the source code foundation needed to start a project, respecting the relationships and patterns defined during modeling.
  • Rapid Project Architecture Setup: Using AI assistants, we can streamline the initial setup of a project by selecting the technology stack, creating folder structures, base files, and configurations according to best practices.
  • Early Validation and Correction: AI can suggest improvements to proposed models, detect inconsistencies, foresee integration issues, and help adapt the design context even before coding begins.

This approach allows students to dedicate more time to understanding the logic behind each component and design principle, instead of spending hours on repetitive setup and basic coding tasks. The conscious and critical use of artificial intelligence strengthens their learning, provides them with more time to innovate, and helps prepare them for real-world industry challenges.

But Not Everything Is Perfect: The Challenges in Programming Techniques

However, not everything is as positive as it seems. In “Programming Techniques,” a course that represents students’ first real contact with application development, the impact of AI is different compared to more advanced subjects. In the past, the repetitive process of writing code—such as creating a simple constructor public Person(), a function public void printFullName() or practicing encapsulation in Java with methods like public void setName(String name) and public String getName()—kept the fundamental programming concepts fresh and clear while coding.

This repetition was not just mechanical; it reinforced their understanding of concepts like object construction, data encapsulation, and procedural logic. It also played a crucial role in developing a solid foundation that made it easier to understand more complex topics, such as design patterns, in future courses.

Nowadays, with the widespread availability and use of AI-based tools and code generators, students tend to skip these fundamental steps. Instead of internalizing these concepts through practice, they quickly generate code snippets without fully understanding their structure or purpose. As a result, the pillars of programming—such as abstraction, encapsulation, inheritance, and polymorphism—are not deeply absorbed, which can lead to confusion and mistakes later on.

Although AI offers the promise of accelerating development and reducing manual labor, it is important to remember that certain repetition and manual coding are essential for establishing a solid understanding of fundamental principles. Without this foundation, it becomes difficult for students to recognize bad practices, avoid common errors, and truly appreciate the architecture and design of robust software systems.

Reflection and Ethical Challenges in Using AI

Recently, I explained the concept of reflection in microservices to my Software Architecture students. To illustrate this, I used the following example: when implementing the Abstract Factory design pattern within a microservices architecture, the Reflection technique can be used to dynamically instantiate concrete classes at runtime. This allows the factory to decide which object to create based on external parameters, such as a message type or specific configuration received from another service. I consider this concept fundamental if we aim to design an architecture suitable for business models that require this level of flexibility.

However, during a classroom exercise where I provided a base code, I asked the students to correct an error that I had deliberately injected. The error consisted of an additional parameter in a constructor—a detail that did not cause compilation failures, but at runtime, it caused 2 out of 5 microservices that consumed the abstract factory via reflection to fail. From their perspective, this exercise may have seemed unnecessary, which led many to ask AI to fix the error.

As expected, the AI efficiently eliminated the error but overlooked a fundamental acceptance criterion: that parameter was necessary for the correct functioning of the solution. The task was not to remove the parameter but to add it in the Factory classes where it was missing. Out of 36 students, only 3 were able to explain and justify the changes they made. The rest did not even know what modifications the AI had implemented.

This experience highlights the double-edged nature of artificial intelligence in learning: it can provide quick solutions, but if the context or the criteria behind a problem are not understood, the correction can be superficial and jeopardize both the quality and the deep understanding of the code.

I haven’t limited this exercise to architecture examples alone. I have also conducted mock interviews, asking basic programming concepts. Surprisingly, even among final-year students who are already doing their internships, the success rate is alarmingly low: approximately 65% to 70% of the questions are answered incorrectly, which would automatically disqualify them in a real technical interview.

Conclusion

Artificial intelligence has become increasingly integrated into academia, yet its use does not always reflect a genuine desire to learn. For many students, AI has turned into a tool for simply getting through academic commitments, rather than an ally that fosters knowledge, creativity, and critical thinking. This trend presents clear risks: a loss of deep understanding, unreflective automation of tasks, and a lack of internalization of fundamental concepts—all crucial for professional growth in technological fields.

Various authors have analyzed the impact of AI on educational processes and emphasize the importance of promoting its ethical and constructive use. As Luckin et al. (2016) suggest, the key lies in integrating artificial intelligence as support for skill development rather than as a shortcut to avoid intellectual effort. Similarly, Selwyn (2019) explores the ethical and pedagogical challenges that arise when technology becomes a quick fix instead of a resource for deep learning.

References:

]]>
https://blogs.perficient.com/2025/12/03/creators-in-coding-copycats-in-class-the-double-edged-sword-of-artificial-intelligence/feed/ 0 388808
Why OneStream is Embracing C# https://blogs.perficient.com/2025/09/19/why-onestream-is-embracing-c/ https://blogs.perficient.com/2025/09/19/why-onestream-is-embracing-c/#respond Fri, 19 Sep 2025 21:25:29 +0000 https://blogs.perficient.com/?p=387273

OneStream, a corporate performance management (CPM) platform, is built on the Microsoft .NET framework, that supports both VB.NET and C# for business rule development. Both languages share the same runtime environment that is known as the .NET Framework. VB.NET has traditionally been favored, especially in finance-related functions. VB.NET does have similarities to Excel’s VBA—making it more accessible to finance professionals who are not full-time developers. However, in recent years, C# has gained significant traction, especially with more technically complex solutions and shared business rules.

In OneStream, shared business rules can be written in either VB.NET or C#, giving developers the freedom to choose based on preference or project requirements. However, item-specific business rules—those tied to a specific dimension, transformation, or form—must still be authored in VB.NET. That said, OneStream is steadily moving toward a C#-first model. Starting with version 7.1, support for C# business rules became more robust, and in the most recent platform updates—especially version 8.0 and beyond—C# has become the default in many marketplace solutions. Notably, several Financial Close extensions, such as Account Reconciliations and Transaction Matching, now require C# for any customization or rule development, reflecting this shift.

The platform’s migration from .NET Framework to .NET 6 in version 8.x is another development. This transition improves performance and scalability but also introduces some changes that can impact coding practices. Legacy VB.NET rules may experience compilation issues due to outdated syntax or incompatible references, prompting many teams to restructure their codebases in line with the updated .NET framework.

The developer community generally views VB.NET as a language with limiting features, while C# is considered the modern standard for .NET development. This sentiment is being adopted by OneStream. For current and future projects, developers and administrators are encouraged to adopt C# for better alignment with OneStream’s roadmap and Microsoft’s broader .NET ecosystem. Still, VB.NET remains relevant for certain rule types and legacy applications, so understanding both remains crucial.

In summary, while VB.NET maintains a presence within OneStream C# is increasingly the preferred and sometimes required language—especially in new marketplace solutions and in platform versions 8.0 and above. With the move to .NET 8, developers should prepare to refactor older rules and adopt C# where possible to ensure compatibility, performance, and long-term maintainability.

]]>
https://blogs.perficient.com/2025/09/19/why-onestream-is-embracing-c/feed/ 0 387273