Thursday, July 24, 2025

Salesforce Apex interview questions

 

Basic Apex Interview Questions

  1. What is Apex in Salesforce?

  2. What are the different data types in Apex?

  3. What are collections in Apex? Name the types.

  4. What is a trigger? When do you use it?

  5. Difference between before and after triggers?

  6. What are governor limits in Salesforce?

  7. What is the difference between SOQL and SOSL?

  8. Explain the use of Map, List, and Set in Apex.

  9. What is a batch class in Apex?

  10. What is the use of @future annotation?


🔹 Intermediate Apex Interview Questions

  1. What is the order of execution in Salesforce?

  2. What are the different types of triggers?

  3. What is the use of Database.insert(record, false)?

  4. What is the difference between public, private, global, and webService access modifiers in Apex?

  5. What are static and instance methods?

  6. What is a wrapper class? Where is it used?

  7. How can you avoid hitting governor limits in Apex?

  8. Explain Test classes and code coverage requirements.

  9. Difference between Database.query() and normal SOQL?

  10. What is a custom metadata type and how is it used in Apex?


🔹 Advanced Apex Interview Questions

  1. How do you handle recursion in triggers?

  2. What is a Queueable class and how is it different from Batch?

  3. Explain Continuation in Apex.

  4. What is dynamic Apex? When would you use it?

  5. What is Apex Scheduler and how do you implement it?

  6. How do you implement Apex Managed Sharing?

  7. What are best practices for writing scalable Apex code?

  8. How do you manage transactions in Apex?

  9. What is the difference between @future, Queueable, Batch, and Schedulable interfaces?

  10. Explain how you can handle large data volumes in Apex.


🔹 Bonus Practical Scenarios

  • How do you prevent duplicate record insertion in triggers?

  • Can we call a batch class from a trigger? How?

  • How to perform error logging in Apex?

  • Describe a situation where you had to refactor poorly written Apex code.

  • How do you ensure bulkification in a trigger?


🔹 Basic Apex Interview Questions & Answers

1. What is Apex in Salesforce?

Answer: Apex is a strongly-typed, object-oriented programming language developed by Salesforce. It allows developers to execute flow and transaction control statements on the Salesforce platform.


2. What are the data types in Apex?

Answer: Apex supports:

  • Primitive: Integer, Double, Long, String, Boolean, Date, Datetime, ID

  • Collections: List, Set, Map

  • Enums, sObjects, Interfaces, and user-defined types.


3. What is a Trigger?

Answer: A trigger is Apex code that executes before or after specific DML operations (insert, update, delete, undelete) on Salesforce records.


4. Difference between before and after triggers?

Answer:

  • before: Used for validation or setting default values before the record is saved to the database.

  • after: Used when data is committed, typically for updating related records or sending emails.


5. What are Governor Limits?

Answer: Salesforce enforces limits to ensure efficient use of resources. Examples:

  • 100 SOQL queries per transaction.

  • 150 DML operations per transaction.

  • 50,000 records returned by SOQL.


6. What is the difference between SOQL and SOSL?

Answer:

  • SOQL (Salesforce Object Query Language): Query records from a single object or related objects.

  • SOSL (Salesforce Object Search Language): Search for text across multiple objects and fields.


7. What is a Collection in Apex?

Answer:

  • List: Ordered collection of elements.

  • Set: Unordered, unique values.

  • Map: Key-value pair storage.


🔹 Intermediate Apex Interview Questions & Answers

8. What is the order of execution in Salesforce?

Answer:

  1. Load original record

  2. Evaluate validation rules

  3. Execute before triggers

  4. Save record (but not commit)

  5. Execute after triggers

  6. Workflow rules, processes, flows

  7. Escalation/assignment rules

  8. Roll-up summaries

  9. Commit record


9. What is a Batch Apex?

Answer: Batch Apex is used to process large volumes of data in chunks asynchronously. It implements Database.Batchable interface.


10. What is a Wrapper Class?

Answer: A wrapper class is a custom object defined by a developer where multiple objects or values can be wrapped into a single unit. Useful in UI and visualforce pages.


11. What is a Static Method?

Answer: A method that belongs to a class rather than an instance of a class. Can be called without instantiating the class.


12. How can you avoid hitting governor limits?

Answer:

  • Use bulkified code

  • Use collections

  • Avoid SOQL/DML inside loops

  • Use @future, Queueable or Batch Apex when needed


13. How do you write a test class in Apex?

Answer:

  • Use @isTest annotation

  • Cover at least 75% of code

  • Use Test.startTest() and Test.stopTest()

  • Assert expected results


14. What is Custom Metadata Type?

Answer: Custom metadata types allow developers to define custom data structures for app configuration and deploy them across orgs.


🔹 Advanced Apex Interview Questions & Answers

15. What is the use of @future annotation?

Answer: Marks a method for asynchronous execution. Cannot return data or take complex types like sObjects as parameters.


16. What is Queueable Apex?

Answer: A more flexible version of @future, allows chaining and processing complex data. Implements Queueable interface.


17. What is Dynamic Apex?

Answer: Allows the ability to access sObject schema, fields, objects dynamically at runtime using Schema class and Type.


18. Difference between Batch, Queueable, and @future?

Feature@futureQueueableBatch Apex
Chaining
Complex Data
Callouts✅ (1 per call)
RecordsLimitedMediumUp to 50 million

19. What is Apex Managed Sharing?

Answer: It allows developers to share records programmatically based on business logic using custom sharing rules.


20. How do you handle recursion in triggers?

Answer: Use a static variable in an Apex class to track whether a trigger has already run to prevent infinite loops.


🔹 Bonus Tips

  • Always bulkify your triggers and logic.

  • Use custom settings/metadata for configurable logic.

  • Write meaningful test cases with assert statements.

  • Know how to use try-catch for error handling.


🔹 Apex Trigger Scenarios

1. Prevent Duplicate Contacts on Account

Scenario: You need to write a trigger to prevent inserting duplicate contact records (same Email) under the same Account.

🧠 Follow-up: How would you bulkify this trigger?


2. Roll-Up Contact Count on Account

Scenario: Create a custom roll-up summary (using Apex) to count the number of contacts related to each account when contact is inserted, updated, or deleted.


3. Trigger Recursion Prevention

Scenario: You have a trigger that updates related records, which in turn fires another trigger on the same object. How would you prevent infinite recursion?


4. Account Rating Based on Opportunity Value

Scenario: If the total amount of all related Opportunities > 1M, mark the Account’s Rating as “Hot”. Implement logic using Apex.


5. Prevent Deletion of Parent If Children Exist

Scenario: Prevent an Account from being deleted if it has active Contacts or Opportunities.


🔹 Asynchronous Apex Scenarios

6. Send Emails to All Contacts

Scenario: On Account update, you need to send an email to all related contacts asynchronously.

🧠 Follow-up: Would you use @future, Queueable, or Batch? Why?


7. Process 100,000 Records

Scenario: You need to update a field for 100,000 Contact records based on custom logic. What Apex solution would you use and why?


8. Chaining Asynchronous Jobs

Scenario: After finishing one batch job (e.g., data cleanup), you want to start another job (e.g., data sync). How would you achieve this?


🔹 Integration & API Scenarios

9. Call External System from Apex

Scenario: On a case update, an external system must be notified via REST API. How would you implement this with callout?

🧠 Follow-up: Can callouts be made from triggers?


10. Retry Failed API Callouts

Scenario: Some external API calls are failing due to timeout. How do you design a retry mechanism in Apex?


🔹 Testing & Deployment Scenarios

11. Test Class for Asynchronous Code

Scenario: You wrote a Queueable class that updates Opportunities. How would you test it, including asynchronous behavior?


12. Test Error Handling

Scenario: Your trigger handles errors using try-catch and logs them. How would you write a test class to ensure the error handling works?


🔹 Security & Sharing Scenarios

13. Restrict Trigger Logic Based on Profile

Scenario: Trigger should only run for users with a specific profile. How would you implement that?


14. Programmatic Sharing

Scenario: A custom object record needs to be shared programmatically with a specific user group. How do you handle this?


🔹 Best Practice Scenarios

15. Avoid SOQL/DML in Loops

Scenario: A junior developer wrote a trigger that performs SOQL and DML inside for loops. How would you refactor it?


16. Dynamic SOQL Use Case

Scenario: Based on user input, the fields to query are dynamic. How would you construct and execute a dynamic SOQL query securely?


🔹 TRIGGERS

1. Prevent Duplicate Contacts on the Same Account

Question: Prevent creating a Contact with the same Email under the same Account.

Answer:

apex

trigger PreventDuplicateContacts on Contact (before insert) { Set<String> emailSet = new Set<String>(); Map<Id, Set<String>> accountEmailMap = new Map<Id, Set<String>>(); for (Contact c : Trigger.new) { if (c.AccountId != null && c.Email != null) { if (!accountEmailMap.containsKey(c.AccountId)) { accountEmailMap.put(c.AccountId, new Set<String>()); } accountEmailMap.get(c.AccountId).add(c.Email.toLowerCase()); } } List<Contact> existingContacts = [SELECT Email, AccountId FROM Contact WHERE AccountId IN :accountEmailMap.keySet() AND Email != null]; for (Contact c : existingContacts) { if (accountEmailMap.containsKey(c.AccountId) && accountEmailMap.get(c.AccountId).contains(c.Email.toLowerCase())) { for (Contact newC : Trigger.new) { if (newC.AccountId == c.AccountId && newC.Email != null && newC.Email.equalsIgnoreCase(c.Email)) { newC.addError('Duplicate contact email under the same Account.'); } } } } }

2. Custom Roll-up Summary: Contact Count on Account

Question: Update a custom field Contact_Count__c on Account when Contacts are inserted or deleted.

Answer:

apex

trigger ContactRollupTrigger on Contact (after insert, after delete, after undelete) { Set<Id> accountIds = new Set<Id>(); if (Trigger.isInsert || Trigger.isUndelete) { for (Contact c : Trigger.new) { if (c.AccountId != null) accountIds.add(c.AccountId); } } else if (Trigger.isDelete) { for (Contact c : Trigger.old) { if (c.AccountId != null) accountIds.add(c.AccountId); } } List<Account> accountsToUpdate = new List<Account>(); for (AggregateResult ar : [ SELECT AccountId, COUNT(Id) count FROM Contact WHERE AccountId IN :accountIds GROUP BY AccountId ]) { accountsToUpdate.add(new Account( Id = (Id)ar.get('AccountId'), Contact_Count__c = (Integer)ar.get('count') )); } update accountsToUpdate; }

3. Prevent Deletion of Account if Active Contacts Exist

Answer:

apex

trigger PreventAccountDeletion on Account (before delete) { Set<Id> accountIds = new Set<Id>(); for (Account acc : Trigger.old) { accountIds.add(acc.Id); } Map<Id, Integer> accountContactMap = new Map<Id, Integer>(); for (AggregateResult ar : [ SELECT AccountId, COUNT(Id) count FROM Contact WHERE AccountId IN :accountIds GROUP BY AccountId ]) { accountContactMap.put((Id)ar.get('AccountId'), (Integer)ar.get('count')); } for (Account acc : Trigger.old) { if (accountContactMap.containsKey(acc.Id)) { acc.addError('You cannot delete this Account because it has related Contacts.'); } } }

🔹 ASYNCHRONOUS APEX

4. Send Email to All Contacts on Account Update (Queueable)

Answer:

apex

public class SendEmailToContactsQueueable implements Queueable { private Id accountId; public SendEmailToContactsQueueable(Id accountId) { this.accountId = accountId; } public void execute(QueueableContext context) { List<Contact> contacts = [SELECT Email FROM Contact WHERE AccountId = :accountId AND Email != null]; for (Contact c : contacts) { Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setToAddresses(new String[]{c.Email}); mail.setSubject('Account Updated'); mail.setPlainTextBody('The related Account has been updated.'); Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail}); } } }
apex

// Call this from a trigger System.enqueueJob(new SendEmailToContactsQueueable(accountId));

5. Process 100,000 Records Using Batch Apex

Answer:

apex

global class ContactBatchUpdate implements Database.Batchable<SObject> { global Database.QueryLocator start(Database.BatchableContext bc) { return Database.getQueryLocator('SELECT Id, Status__c FROM Contact'); } global void execute(Database.BatchableContext bc, List<Contact> scope) { for (Contact c : scope) { c.Status__c = 'Processed'; } update scope; } global void finish(Database.BatchableContext bc) { System.debug('Batch Completed'); } }

🔹 INTEGRATION SCENARIOS

6. Call External API on Case Update

Answer:

apex

public class CaseCallout { @future(callout=true) public static void notifyExternalSystem(Id caseId) { Case c = [SELECT Id, Subject FROM Case WHERE Id = :caseId]; HttpRequest req = new HttpRequest(); req.setEndpoint('https://example.com/api/case'); req.setMethod('POST'); req.setBody(JSON.serialize(c)); req.setHeader('Content-Type', 'application/json'); Http http = new Http(); HttpResponse res = http.send(req); System.debug(res.getBody()); } }

⚠️ Cannot call web services from triggers directly — use @future or Queueable.


🔹 SECURITY & SHARING

7. Share a Custom Record with Specific Users Programmatically

Answer:

apex

Custom_Object__Share shareRec = new Custom_Object__Share(); shareRec.ParentId = 'a0Dxxxxxxxxxxxx'; // Record Id shareRec.UserOrGroupId = '005xxxxxxxxxxxx'; // User Id shareRec.AccessLevel = 'Edit'; shareRec.RowCause = Schema.Custom_Object__Share.RowCause.Manual; insert shareRec;

🔹 TESTING & BEST PRACTICES

8. Write a Test Class for Queueable Class

Answer:

apex

@isTest private class TestSendEmailQueue { @isTest static void testQueueable() { Account acc = new Account(Name='Test'); insert acc; Contact con = new Contact(LastName='Tester', Email='test@example.com', AccountId=acc.Id); insert con; Test.startTest(); System.enqueueJob(new SendEmailToContactsQueueable(acc.Id)); Test.stopTest(); } }

9. Avoid SOQL/DML in Loops

Bad:

apex

for (Contact c : contacts) { Account a = [SELECT Name FROM Account WHERE Id = :c.AccountId]; }

Good:

apex

Set<Id> accountIds = new Set<Id>(); for (Contact c : contacts) accountIds.add(c.AccountId); Map<Id, Account> accountMap = new Map<Id, Account>( [SELECT Name FROM Account WHERE Id IN :accountIds]); for (Contact c : contacts) { Account a = accountMap.get(c.AccountId); }

Friday, July 18, 2025

Lightning Web Components Questions


1. What is Lightning Web Component (LWC)?

Answer:
LWC is a modern UI framework developed by Salesforce to build web applications using standard web technologies like HTML, CSS, and JavaScript. It leverages Web Components standards and provides better performance than Aura components.


2. What are the differences between Aura Components and LWC?

Answer:

Feature Aura LWC
Base Custom Salesforce framework Standard Web Components
Performance Slower Faster
Browser Support Polyfilled Uses native APIs
Syntax Verbose Cleaner, modern JavaScript

3. What are the main files in an LWC component?

Answer:

  • .html – Template (HTML)

  • .js – JavaScript controller

  • .js-meta.xml – Metadata configuration

  • .css (optional) – Styling


4. How do you communicate between LWC components?

Answer:

  • Parent to Child: Using public properties (@api)

  • Child to Parent: Using custom events (this.dispatchEvent(new CustomEvent('eventname')))

  • Sibling: Using a common parent or Pub/Sub/Event Service


5. What is @api, @track, and @wire in LWC?

Answer:

  • @api: Public property accessible from parent

  • @track: (legacy) Reactive private property (now all fields are reactive by default)

  • @wire: Used to read data from Salesforce or call Apex methods declaratively


6. How do you call Apex methods in LWC?

Answer:
Use @wire for reactive access or use import with async/await:

import myMethod from '@salesforce/apex/MyClass.myMethod';

async connectedCallback() {
   const result = await myMethod({ param: value });
}

7. What is a Lightning Data Service (LDS)?

Answer:
LDS allows you to access, create, delete, and update records without Apex by using <lightning-record-form>, <lightning-record-edit-form>, etc.


8. What are lifecycle hooks in LWC?

Answer:

  • constructor(): Initialization

  • connectedCallback(): DOM inserted

  • renderedCallback(): Render complete

  • disconnectedCallback(): Cleanup

  • errorCallback(): Error handling


9. How do you share data between components that are not in the same DOM hierarchy?

Answer:
Use:

  • Lightning Message Service (LMS) – for cross-DOM component communication

  • Custom Event – for child-parent or simple scenarios


10. What is the role of the js-meta.xml file in LWC?

Answer:
It defines the component’s metadata like:

  • Component visibility (targets: lightning__RecordPage, etc.)

  • API version

  • Configuration parameters


11. What are wire adapters and how do they differ from imperative calls?

Answer:

  • @wire: Declarative, automatic, reactive to parameter changes

  • Imperative: Manual call using async/await or .then()


12. Explain Shadow DOM in LWC.

Answer:
Shadow DOM encapsulates the component’s styles and DOM so they don’t clash with outer components. It ensures style and structure isolation.


13. What are decorators in LWC?

Answer:
Decorators like @api, @track, and @wire are used to annotate properties and methods to control accessibility, reactivity, or data binding.


14. How do you handle errors in LWC?

Answer:

  • Use try/catch in imperative Apex calls

  • errorCallback() for component-level errors

  • Handle error responses gracefully in the UI


15. What are some performance optimization tips in LWC?

Answer:

  • Use @wire where possible

  • Avoid large DOM re-renders

  • Use pagination for large datasets

  • Debounce input handlers

  • Use Lightning Data Table efficiently



Salesforce LWC scenario based interview questions

 

Component Communication

  1. Scenario: You have a parent component showing a list of accounts, and each account has a child component for showing contacts. How would you send the selected account record from parent to child?

    • Follow-up: How would the child notify the parent when a contact is selected?

  2. Scenario: How would you handle communication between two sibling LWC components placed on the same Lightning Page?


🔹 Data Handling & Apex Integration

  1. Scenario: You need to fetch a list of Opportunities and display them in a table. But the list needs to update dynamically every time a new Opportunity is created. How would you achieve this?

  2. Scenario: You call an Apex method from LWC that returns a large amount of data. What techniques can you use to improve performance and reduce load time?


🔹 Error Handling

  1. Scenario: Your component uses @wire to fetch records. How do you handle errors from the wire service and display appropriate messages to the user?

  2. Scenario: You are invoking an Apex method imperatively and it returns an exception. How do you gracefully handle and log the error?


🔹 Custom Events & Event Propagation

  1. Scenario: You have a nested LWC structure (Parent → Intermediate → Child). The child fires an event. How does the parent catch it?


🔹 Navigation & Record Handling

  1. Scenario: You need to create a custom component that opens a record in edit mode when a user clicks a button. How would you do that using LWC?

  2. Scenario: How do you handle record creation in LWC and redirect the user to the record detail page once it's saved?


🔹 Lifecycle & Rendering

  1. Scenario: Your LWC fetches records in connectedCallback() but data changes are not reflected when the user navigates back to the component. How do you fix that?

  2. Scenario: You need to perform a DOM operation only after the component renders completely. Which lifecycle hook will you use?


🔹 Design & Reusability

  1. Scenario: You are designing a component that will be used on multiple record pages for different objects. How would you make it dynamic to handle any object?


🔹 Security & Performance

  1. Scenario: Your LWC is throwing a FIELD_INTEGRITY_EXCEPTION when trying to access a field. What could be the cause and how do you resolve it?

  2. Scenario: How would you lazy-load data in an LWC to improve performance on large datasets?


🔹 Testing & Debugging

  1. Scenario: Your LWC is not rendering data as expected, but no errors are shown. How do you debug the issue?



1. Parent to Child Communication in LWC

Q: You have a parent component showing a list of accounts and each account is passed to a child component. How do you pass data from parent to child?

A:
Use @api property in the child component to accept data from the parent.

Child Component:

js // childComponent.js
import { LightningElement, api } from 'lwc'; export default class ChildComponent extends LightningElement { @api accountRecord; }

Parent Component:

html
<template> <template for:each={accountList} for:item="acc"> <c-child-component key={acc.Id} account-record={acc}></c-child-component> </template> </template>

2. Child to Parent Communication

Q: How would a child component notify the parent when a contact is selected?

A:
Use Custom Events in the child and handle it in the parent.

Child Component:

js
handleContactSelect() { const event = new CustomEvent('contactselected', { detail: { contactId: this.selectedContactId } }); this.dispatchEvent(event); }

Parent Component HTML:

html
<c-child-component oncontactselected={handleContactSelection}></c-child-component>

Parent JS:

js
handleContactSelection(event) { const contactId = event.detail.contactId; // Do something with the selected contact ID }

3. Fetching Dynamic Records with Refresh

Q: How to refresh a wire when a new record is created?

A:
Use refreshApex() after creating the new record.

js
import { refreshApex } from '@salesforce/apex'; import getOpportunities from '@salesforce/apex/OpportunityController.getOpportunities'; @wire(getOpportunities) opps; createOpportunity() { // Call Apex to create opportunity createOpp().then(() => { refreshApex(this.opps); }); }

4. Handling Errors in Wire Service

Q: How do you handle errors returned from wire services?

A:

js
@wire(getAccounts) wiredAccounts({ error, data }) { if (data) { this.accounts = data; } else if (error) { console.error('Error:', error); this.error = 'Failed to load accounts'; } }

5. Navigate to Record Page

Q: How to navigate to a record page in edit mode?

A:
Use NavigationMixin.

js
import { NavigationMixin } from 'lightning/navigation'; export default class NavigateToRecord extends NavigationMixin(LightningElement) { navigateToEditRecord() { this[NavigationMixin.Navigate]({ type: 'standard__recordPage', attributes: { recordId: this.recordId, objectApiName: 'Account', actionName: 'edit' } }); } }

6. Sibling Component Communication

Q: How do sibling LWC components on the same Lightning Page communicate?

A:
Use Lightning Message Service (LMS).

Step 1: Create Message Channel (via messageChannels folder in metadata)

Step 2: Publish Message in Sender

js
import { publish, MessageContext } from 'lightning/messageService'; import SAMPLEMC from '@salesforce/messageChannel/SampleMessageChannel__c'; @wire(MessageContext) messageContext; publishMessage() { const payload = { recordId: '001XXXXXXXXXXXX' }; publish(this.messageContext, SAMPLEMC, payload); }

Step 3: Subscribe in Receiver

js
import { subscribe, MessageContext } from 'lightning/messageService'; @wire(MessageContext) messageContext; connectedCallback() { this.subscription = subscribe(this.messageContext, SAMPLEMC, (message) => { this.handleMessage(message); }); }

7. Lazy Loading Data for Performance

Q: How can you implement lazy loading in an LWC data table?

A:
Use onscroll or the onloadmore event of lightning-datatable.

html
<lightning-datatable key-field="id" data={data} columns={columns} onloadmore={loadMoreData}> </lightning-datatable>
js
loadMoreData(event) { // Fetch next set of records and append to this.data }

8. Dynamic Component for Any Object

Q: How do you build a reusable component that can show records for any object?

A:
Use @api objectApiName and @wire(getObjectInfo).

js
@api objectApiName; @wire(getObjectInfo, { objectApiName: '$objectApiName' }) objectInfo;

This allows the component to behave differently based on the object type passed from parent or app builder.


9. Accessing Related Fields in Apex

Q: You’re getting a FIELD_INTEGRITY_EXCEPTION when accessing a related field. What’s the issue?

A:
Likely causes:

  • Field is not accessible due to FLS.

  • Incorrect field path in Apex query (e.g., Account.Name should be accessible only if you include it in SELECT).

  • Check for null parent objects (e.g., Opportunity.Account.NameOpportunity.Account might be null).


10. Lifecycle Hook for DOM Access

Q: You want to manipulate the DOM after the component is rendered. Which hook do you use?

A:
Use renderedCallback().

js
renderedCallback() { const element = this.template.querySelector('.myClass'); // Manipulate element }

Friday, November 3, 2023

REST API Design Patterns

 uncommon scenarios.

Types of API Design Patterns

Following are some of the commonly used API design patterns:

  1. RESTful API:

  • Uses HTTP methods to interact with resources
  • Supports caching and scalability
  • Works well for CRUD (Create, Read, Update, Delete) operations
  • Allows for stateless communication between client and server
  • Can be used with a variety of programming languages and frameworks

2. RPC API:

  • Uses Remote Procedure Calls to interact with a remote server
  • Typically requires a protocol or API definition, such as Protobuf or gRPC
  • Can be more efficient than RESTful API in terms of network usage
  • Can be more difficult to implement and maintain

3. GraphQL API:

  • Allows clients to request exactly the data they need
  • Provides a single endpoint for clients to make requests
  • Can reduce the number of requests needed to get all required data
  • Can be more complex to implement than RESTful API
  • May require additional tooling and libraries

4. SOAP API:

  • Uses a messaging protocol to exchange structured information
  • Can be used with a variety of programming languages and frameworks
  • Can support more complex operations than RESTful API
  • Can be more difficult to implement and maintain

5. Hypermedia API:

  • Includes links between resources, allowing for dynamic discovery and navigation
  • Can improve the flexibility and adaptability of an API
  • May require additional tooling and libraries
  • Can be more difficult to implement and maintain

6. Event-driven API:

  • Sends notifications to clients when certain events occur
  • Can reduce the need for clients to repeatedly poll for updates
  • Can be useful for real-time applications
  • Can be more difficult to implement and maintain

7. Message Queue API:

  • Allows applications to send and receive messages asynchronously
  • Can provide a reliable and scalable way to process messages
  • Can be useful for distributed systems
  • May require additional infrastructure and tooling

In general, the choice of API design pattern will depend on the specific needs of the project and the system architecture. RESTful API is often a good choice for simple CRUD operations, while GraphQL may be a better choice for complex queries. RPC API and SOAP API can be more efficient for certain types of operations but can be more complex to implement and maintain. Hypermedia API, event-driven API, and message queue API can be useful for certain types of systems and applications but may require additional tooling and infrastructure.

REST API Design Patterns

When designing API projects, enterprises prefer to build upon the REST best practices and guidelines for web services.

REST (Representational State Transfer) API (Application Programming Interface) design patterns are a set of best practices and conventions for designing web services that follow the principles of the REST architectural style. These patterns are used to structure the endpoints, resources, and data models of RESTful APIs in a way that promotes simplicity, scalability, and ease of use.

Some common REST API design patterns include:

  • Resource-Based: This pattern focuses on organizing API endpoints around resources, which represent entities in the system being exposed via the API.
  • CRUD (Create, Read, Update, Delete): This pattern is a common approach for defining the four basic operations (create, read, update, delete) that can be performed on a resource.
  • HATEOAS (Hypermedia as the Engine of Application State): This pattern involves including hyperlinks in API responses that allow clients to discover and navigate the API resources.
  • Filter and Pagination: This pattern involves implementing filtering and pagination capabilities to allow clients to efficiently retrieve subsets of data from a resource.
  • Versioning: This pattern involves providing different versions of an API to support changes in the API without breaking existing clients.

By following these and other REST API design patterns, developers can create APIs that are easy to understand, maintain, and use, and that can scale to meet the needs of large and complex systems.

Understanding REST API design- 6 Key constraints every engineer must know

When designing a REST API, it is important to be aware of several key constraints that define the characteristics and capabilities of the API. These constraints are:

  1. Client-server architecture: This constraint requires that the client and server be separated from each other, with each responsible for a specific set of functionalities. This separation allows for greater scalability and flexibility in the system, as the client and server can be updated or replaced independently of each other.
  2. Statelessness: A RESTful API should be stateless, meaning that each request contains all the necessary information for the server to understand and respond to it. The server does not maintain any session state between requests, which makes the system more scalable and easier to manage.
  3. Cacheability: REST APIs should be designed to take advantage of caching, which can improve performance by reducing the number of requests sent to the server. Responses should include information that allows clients to determine whether the response can be cached, and for how long.
  4. Layered system: A RESTful API should be designed as a layered system, where each layer provides a specific set of functionalities. This allows for greater flexibility in the system, as layers can be added, removed, or modified without affecting the rest of the system.
  5. Uniform interface: The uniform interface constraint defines the standard interface that all components of the API must adhere to. This includes the use of standard HTTP methods (GET, POST, PUT, DELETE) for CRUD operations, as well as a consistent data format (usually JSON or XML) for requests and responses.
  6. Code on demand: This is an optional constraint that allows for executable code to be transferred from the server to the client, which can add additional functionality and flexibility to the API. However, this constraint is not commonly used in RESTful APIs and should be used with caution, as it can add complexity to the system.

RESTful API Design Patterns: A Comprehensive Overview

No alt text provided for this image

The diagram shows the different components and design patterns that can be used in RESTful API design. The client makes HTTP requests to interact with the resources. The resources can be either collections or items, and the HTTP methods used to interact with them include GET, POST, PUT, and DELETE.

Additionally, there are other design patterns such as filters, pagination, search, and sorting that can be applied to resources. The API can also support actions that do not map to CRUD operations, and these can be implemented using custom endpoints.


To sum up, the diagram shows that RESTful APIs can support multiple data formats such as JSON, XML, etc., and can also use versioning techniques to manage changes to the API over time.

RESTful API Best Practices

RESTful APIs have become the standard for building web services that are scalable, flexible, and easy to maintain. However, building a successful RESTful API requires careful planning, implementation, and testing. In this answer, we'll cover some of the best practices for building a RESTful API, as well as some common pitfalls to avoid.

Best Practices to be considered:

  1. Follow the REST architectural style: The REST architectural style defines a set of constraints that must be followed to build a RESTful API. These constraints include using HTTP methods correctly, using resource URIs, and using hypermedia to link resources. Make sure you follow these constraints to ensure that your API is consistent, reliable, and easy to understand.
  2. Use HTTP methods correctly: Use HTTP methods like GET, POST, PUT, and DELETE to perform the appropriate action on a resource. For example, use GET to retrieve a resource, POST to create a new resource, PUT to update an existing resource, and DELETE to delete a resource.
  3. Use resource URIs: Use resource URIs to identify resources in your API. The URI should be unique and consistent, and it should not include any implementation details. For example, instead of using a URI like /API/users/getUserById, use a URI like /API/users/123.
  4. Use hypermedia to link resources: Use hypermedia to link resources in your API. Hypermedia allows clients to discover related resources and navigate the API without having to know the implementation details. Use hypermedia formats like HAL, JSON-LD, or Siren to provide links to related resources.
  5. Use versioning: Use versioning to ensure that changes to your API do not break existing clients. Include a version number in the URI or in the HTTP header to indicate which version of the API is being used.
  6. Use authentication and authorization: Use authentication and authorization to secure your API. Use OAuth 2.0 or a similar protocol to authenticate clients and control access to resources.
  7. Use error handling: Use error handling to provide informative error messages when errors occur. Use HTTP status codes to indicate the type of error, and include an error message in the response body.