diff --git a/doc/port-fec/fec-auto-determination.md b/doc/port-fec/fec-auto-determination.md
new file mode 100644
index 0000000000..8e3b53dc84
--- /dev/null
+++ b/doc/port-fec/fec-auto-determination.md
@@ -0,0 +1,187 @@
+# SONiC FEC Auto Determination Design #
+
+## Table of Content
+
+- [Revision](#revision)
+- [Scope](#scope)
+- [Definitions/Abbreviations](#definitions/abbreviations)
+- [Overview](#overview)
+- [High-Level Design](#high-level-design)
+- [API design](#api-design)
+- [Common Rule for FEC Determination](#common-rule-for-fec-determination)
+ - [Table 1: FEC Mapping Based on Optics Type](#table-1-fec-mapping-based-on-optics-type)
+ - [Table 2: FEC Mapping Based on Lane Speed and Number of Lanes](#table-2-fec-mapping-based-on-lane-speed-and-number-of-lanes)
+- [Diagram For Different Use Cases](#diagram-for-different-use-cases)
+- [Dependency](#dependency)
+
+### Revision
+
+ | Rev | Date | Author | Change Description |
+ |:---:|:-----------:|:-------------------:|--------------------------------------------|
+ | 0.1 | | Shyam Kumar, Longyin Huang | Initial version |
+
+### Scope
+This document is the design document for FEC auto-determination feature on SONiC.
+
+### Definitions/Abbreviations
+| **Term** | **Definition** |
+| -------------- | ------------------------------------------------ |
+| FEC | Forward Error Correction |
+| DPB | Dynamic Port Breakout |
+
+### Overview
+
+FEC mode is a critical configuration for a port, which needs to be configured properly for the port to come up.
+
+There are below scenarios that can end up with wrong FEC mode:
+1. In DPB(Dynamic Port Breakout) case, today's DPB CLI doesn't generate FEC config for newly created ports, FEC mode is default to `none` at [SAI/SDK](https://github.com/opencomputeproject/SAI/blob/a94bbbe43242a4d9e1a4d9f70780ea9251127f5d/inc/saiport.h#L1012) layer.
+2. In non-DPB case,
+ - Some platforms have no FEC configured in CONFIG_DB by default. The FEC mode can be either default to `none` at SAI/SDK layer or manually configured by user who might not have enough domain knowledge.
+ - Some platforms have default FEC defined in `port_config.ini`, which however might not be suitable for the specific port/optics on the system.
+
+The feature in this document is to address the issue in both of above scenarios in a common platform-independent way, since the rule to determine FEC for a given port/optics is common for all platforms.
+
+### High-Level Design
+
+Add `determine-fec` module which can determine FEC mode based on common rule for a given port with a given optics. This module provides a `determine_fec` API which can be invoked in below use cases:
+1. DPB use case: Enhance today's DPB CLI to automatically determine and configure FEC in CONFIG_DB for dynamically created ports, based on determine-fec module.
+2. non-DPB use case: Add a user-triggered CLI `fec-auto-correct` to automatically determine and configure FEC in CONFIG_DB for existing ports, based on determine-fec module.
+ - Future plan: determine-fec module can be further enhanced to be integrated with xcvrd, which can be triggered automatically during transceiver insertion, without human intervention. (details TBD)
+
+### API design
+```
+def determine_fec(lane_speed: int, num_lanes: int, optics_type: Optional[str] = None) -> str:
+ """
+ Determines the appropriate Forward Error Correction (FEC) type based on lane speed, number of lanes, and optics type for a specific logical port.
+ This logic is based on FEC mapping rules common for all platforms.
+
+ Parameters:
+ - lane_speed (int): The speed of each lane in GB.
+ - num_lanes (int): The total number of lanes.
+ - optics_type (Optional[str]): The type of optics in use. Can be None if not applicable.
+
+ Returns:
+ - str: The recommended FEC type based on the common rules. It can be either 'none'/'rs'/'fc'.
+
+ Example:
+ >>> determine_fec(25, 4, "100G-SR4")
+ "rs"
+
+ """
+```
+
+### Common Rule for FEC Determination
+
+#### Table 1: FEC Mapping Based on Optics Type
+| Optics Type | FEC |
+|-------------|------|
+| 40G | none |
+| 100G-DR | none |
+| 100G-FR | none |
+| 100G-LR | none |
+| 100G-LR4 | none |
+| 100G-ER4 | none |
+| 100G AOC | none |
+| 400G | rs |
+| ALL_OTHER | rs |
+
+#### Table 2: FEC Mapping Based on Lane Speed and Number of Lanes
+| Lane Speed | Number of Lanes (per Logical Port) | FEC |
+|------------|-----------------------------------|------|
+| 10 | 1 | none |
+| 10 | 4 | none |
+| 20 | 2 | none |
+| 25 | 1 | rs |
+| 25 | 2 | rs |
+| 25 | 4 | rs |
+| 25 | 8 | rs |
+| 50 | 1 | rs |
+| 50 | 2 | rs |
+| 50 | 4 | rs |
+| 50 | 8 | rs |
+| 50 | 16 | rs |
+
+Above tables can be defined as JSON file, and be loaded by determine-fec module. Platform can also override the default FEC mapping by providing its own JSON file.
+
+> [!NOTE]
+> If a port has matched FEC entry in both above tables, then prefers FEC entry in first table. (Only exception: For `lane_speed=10, num_lane=1 or 4`, we prefer FEC entry in second table)
+
+
+### Diagram For Different Use Cases
+
+```mermaid
+sequenceDiagram
+ title FEC determination in DPB case
+
+ actor user as User
+ participant dpb_cli as DPB CLI
+ participant determine_fec as determine-fec module
+ participant config_db as CONFIG_DB
+ participant syncd as SYNCD
+
+
+ user ->>+ dpb_cli: do breakout on a port
+ note over dpb_cli: run today's flow per port:
+ dpb_cli ->>+ dpb_cli: generate the config(speed/lanes/etc) for each new port
+
+ note over dpb_cli,determine_fec: run below additional logic per port:
+ dpb_cli ->>+ determine_fec: call API determine_fec(lane_speed, num_lanes) per port
+ determine_fec ->>+ determine_fec: calculate FEC mode based on common rule
+ determine_fec -->>- dpb_cli: return FEC mode
+
+ note over dpb_cli, syncd: run today's flow:
+ dpb_cli ->>+ config_db: Add new ports in PORT table (today's flow),
additionally with proper FEC if determined above
+
+ par
+ config_db -->>- dpb_cli: Done
+ and
+ config_db ->>+ syncd: notify for new port creation
+ end
+
+ dpb_cli -->>- user: Done
+```
+
+```mermaid
+sequenceDiagram
+ title FEC determination in non-DPB case
+
+ actor user as User
+ participant fec_correct_cli as fec-auto-correct CLI
(just a wrapper)
+ participant determine_fec as determine-fec module
+ participant state_db as STATE_DB
+ participant config_db as CONFIG_DB
+ participant syncd as SYNCD
+
+ user ->>+ fec_correct_cli: auto-correct FEC mode for all ports
+ fec_correct_cli ->>+ determine_fec: call API correct_fec_for_all_ports()
+
+ loop every port
+ determine_fec ->>+ state_db: read optics_type from TRANSCEIVER_INFO table
+ state_db -->>- determine_fec: return optics_type
+ determine_fec ->>+ determine_fec: internally call API determine_fec(lane_speed, num_lanes, optics_type)
which calculates FEC mode based on common rule
+ end
+
+ determine_fec ->>+ config_db: update FEC if needed
+
+ par
+ config_db -->>- determine_fec: Done
+ and
+ config_db ->>+ syncd: notify for FEC update
+ end
+
+ determine_fec -->>- fec_correct_cli: Done
+ fec_correct_cli -->>- user: Done
+
+```
+
+> [!NOTE]
+> In the above use cases, automatically determined FEC mode is saved in running config, user needs to do ```config save``` to save it permanently.
+
+### Dependency
+A new ```optics_type``` field (human-readable type for optics, such as ```100G-DR```, ```100G-FR```, etc) will be added to TRANSCEIVER_INFO table, so that determine-fec module can read it for the non-DPB use case.
+
+To implement this, ```optics_type``` can be determined based on today's transceiver_info, and be added as part of output of API [get_transceiver_info()](https://github.com/sonic-net/sonic-platform-common/blob/1988b37c7668394f38f155c86f5462a4461fe82e/sonic_platform_base/sonic_xcvr/api/xcvr_api.py#L42-L71) in ```sonic-platform-common``` repo.
+
+```optics_type``` field can also provide benefits in readability/service-ability/debug-ability:
+1. help user/engineer to easily and quickly identify what optics are plugged onto the router (if it can be added to show CLI output later)
+2. test script can easily figure out the optics type based on this single ```optics_type``` field and do test actions accordingly.