Troubleshooting 502 Bad Gateway Nginx

Avatar

By squashlabs, Last Updated: September 6, 2023

Troubleshooting 502 Bad Gateway Nginx

Table of Contents

Introduction to 502 Bad Gateway Nginx

The 502 Bad Gateway error is a common issue encountered when using Nginx as a web server or a reverse proxy. It occurs when Nginx acts as an intermediary server and receives an invalid response from an upstream server. This error can disrupt the normal functioning of websites and web applications, causing frustration for both developers and users.

Related Article: How to Validate IPv4 Addresses Using Regex

Common Causes of the 502 Bad Gateway Error

There are several common causes for the 502 Bad Gateway error in Nginx. Understanding these causes can help in troubleshooting and resolving the issue effectively.

1. Connection Issues with Upstream Server

One possible cause of the 502 Bad Gateway error is a connection problem between Nginx and the upstream server. This can occur due to various reasons, such as the upstream server being down or unresponsive, network connectivity issues, or misconfigured proxy settings.

To troubleshoot this issue, you can check the connectivity to the upstream server using tools like curl or telnet. Additionally, inspecting the Nginx error logs can provide valuable information about the specific error encountered.

2. Timeouts and Slow Upstream Server Response

Another common cause of the 502 error is when the upstream server takes too long to respond or exceeds the configured timeout settings. This can happen if the upstream server is overloaded, experiencing performance issues, or has a slow network connection.

To address this issue, it is important to configure appropriate timeout settings in the Nginx configuration file. This ensures that Nginx waits for a reasonable amount of time for the upstream server to respond before timing out.

Related Article: How to Do Sorting in C++ & Sorting Techniques

Inspecting Nginx Configuration Files

Inspecting the Nginx configuration files is an essential step in troubleshooting the 502 Bad Gateway error. The configuration files contain important settings that determine how Nginx handles requests and communicates with upstream servers.

To inspect the Nginx configuration files, you can navigate to the directory where the files are located, typically in /etc/nginx/. The main configuration file is usually named nginx.conf, and additional configuration files may be included from this file.

Within these configuration files, you can find various directives that control Nginx’s behavior. It is important to review these directives, paying close attention to settings related to proxying requests to upstream servers, timeouts, and error handling.

Example: Inspecting Nginx Configuration File

Here is an example of an Nginx configuration file snippet that sets up a reverse proxy to an upstream server:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://upstream_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this example, the proxy_pass directive specifies the upstream server to which requests should be forwarded. The proxy_set_header directives are used to set the appropriate headers for the proxy request.

Inspecting and understanding these configuration settings can help identify potential misconfigurations or issues that may be causing the 502 Bad Gateway error.

Use Case: High Traffic Website

One common scenario where the 502 Bad Gateway error may occur is when a website experiences high traffic or sudden spikes in user requests. This can overload the upstream servers and cause them to respond slowly or become unresponsive.

To handle high traffic effectively, it is important to configure Nginx to handle a larger number of concurrent connections and optimize its performance.

Related Article: How to Use JSON Parse and Stringify in JavaScript

Example: Configuring Nginx for High Traffic

To configure Nginx for high traffic, you can adjust various settings in the Nginx configuration file. Here are a few examples:

http {
    # Increase the maximum number of simultaneous connections
    worker_connections 1024;

    # Enable keep-alive connections to reuse TCP connections
    keepalive_timeout 65;

    # Increase the buffer size to handle larger requests
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;

    # Enable Gzip compression to reduce the size of the response
    gzip on;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_types text/plain text/css application/json;
}

In this example, worker_connections sets the maximum number of simultaneous connections that Nginx can handle. Increasing this value allows Nginx to handle more concurrent connections from high-traffic websites.

The keepalive_timeout directive enables keep-alive connections, allowing Nginx to reuse TCP connections for subsequent requests. This helps reduce the overhead of establishing new connections for each request.

The client_header_buffer_size and large_client_header_buffers directives increase the buffer size for handling larger requests. This ensures that Nginx can handle larger payloads without encountering buffer overflow errors.

Enabling Gzip compression using the gzip directive helps reduce the size of the response sent to the client. This can significantly improve the performance of the website, especially when serving large amounts of static content.

By configuring Nginx to handle high traffic efficiently, you can mitigate the occurrence of the 502 Bad Gateway error and ensure a smooth user experience even during peak periods.

Best Practice: Configuring Nginx Timeout Settings

Configuring appropriate timeout settings in Nginx is crucial for avoiding the 502 Bad Gateway error. Timeout settings determine how long Nginx waits for various operations, such as establishing connections, reading responses from upstream servers, and sending responses to clients.

Example: Configuring Nginx Timeout Settings

Here is an example of how you can configure timeout settings in Nginx:

http {
    # Set the timeout for establishing connections with upstream servers
    proxy_connect_timeout 5s;

    # Set the timeout for receiving a response from upstream servers
    proxy_read_timeout 60s;

    # Set the timeout for sending a response to clients
    send_timeout 10s;
}

In this example, proxy_connect_timeout sets the maximum time Nginx waits to establish a connection with an upstream server. If the connection cannot be established within this time, Nginx returns a 502 Bad Gateway error.

The proxy_read_timeout directive specifies the maximum time Nginx waits for a response from an upstream server after a connection has been established. If the response is not received within this time, Nginx considers the request as failed and returns a 502 error.

The send_timeout directive sets the maximum time Nginx waits for the entire response to be sent to the client. If the response cannot be sent within this time, Nginx terminates the connection and returns a 502 error.

By configuring appropriate timeout settings, you can ensure that Nginx waits a reasonable amount of time for upstream servers to respond, reducing the occurrence of the 502 Bad Gateway error.

Related Article: How to Implement Min Heap Binary Trees

Real World Example: Solving 502 Error on an E-commerce Site

In a real-world scenario, imagine an e-commerce website that uses Nginx as a reverse proxy to handle incoming requests and forwards them to multiple backend servers. The website suddenly starts experiencing intermittent 502 Bad Gateway errors, causing frustration for both the website owners and users.

To troubleshoot and resolve this issue, the following steps can be taken:

Step 1: Inspect Nginx Configuration

First, inspect the Nginx configuration files to ensure there are no misconfigurations or issues with proxying requests to the backend servers. Pay close attention to the proxy_pass directive and ensure it points to the correct backend server addresses.

Step 2: Check Upstream Server Health

Next, check the health of the upstream servers to ensure they are operating properly. Use tools like curl or telnet to test the connectivity to the backend servers and verify that they are responsive.

Related Article: How to Implement and Use Generics in Typescript

Step 3: Adjust Timeout Settings

If the upstream servers are functioning correctly, consider adjusting the timeout settings in the Nginx configuration file. Increase the values for proxy_connect_timeout, proxy_read_timeout, and send_timeout to allow more time for the backend servers to respond.

Step 4: Monitor Server Resources

Monitor the server resources, including CPU, memory, and network usage, to identify any bottlenecks or performance issues. High resource utilization can cause delays in server response times and lead to the 502 error. Consider upgrading server hardware or optimizing the application code if necessary.

Step 5: Implement Load Balancing

To distribute the incoming traffic evenly across multiple backend servers, consider implementing load balancing using Nginx. Load balancing helps to improve the overall performance and reliability of the system by distributing the workload effectively.

Related Article: How to Use If-Else Statements in Shell Scripts

Step 6: Enable Nginx Logging

Enable detailed logging in Nginx to capture information about the requests and responses. Analyzing the logs can provide valuable insights into the cause of the 502 errors and help in troubleshooting.

Performance Consideration: Optimizing Nginx for High Performance

Optimizing Nginx for high performance is essential to ensure fast and responsive web applications. By fine-tuning various settings and implementing performance best practices, you can enhance the overall performance of your Nginx server.

Example: Optimizing Nginx for High Performance

Here are some performance optimization techniques for Nginx:

http {
    # Enable the use of multiple worker processes
    worker_processes auto;

    # Limit the number of connections per worker process
    worker_connections 1024;

    # Enable sendfile for optimized file transfers
    sendfile on;

    # Enable TCP fastopen for faster connection establishment
    tcp_fastopen on;

    # Enable TCP keepalive to detect and close idle connections
    tcp_keepalive_timeout 60s;

    # Enable HTTP/2 for improved performance
    listen 443 ssl http2;

    # Enable server-side caching for static files
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
    }
}

In this example, worker_processes is set to auto, allowing Nginx to utilize multiple worker processes for handling concurrent connections. Adjust the worker_connections value to limit the number of connections per worker process based on your server’s capacity.

Enabling sendfile allows Nginx to use the operating system’s optimized file transfer mechanism, improving the efficiency of static file serving.

Enabling tcp_fastopen enables TCP Fast Open, which allows data to be sent during the TCP handshake, reducing connection establishment latency.

Setting a reasonable tcp_keepalive_timeout value helps detect and close idle connections, freeing up server resources.

Enabling HTTP/2 with the listen directive allows for improved performance and reduced latency by multiplexing multiple requests over a single TCP connection.

Implementing server-side caching for static files using the expires directive helps reduce the load on the backend servers and improves response times for subsequent requests.

By implementing these performance optimization techniques, you can significantly enhance the performance of your Nginx server and improve the overall user experience.

Related Article: How to Use Generics in Go

Advanced Technique: Debugging with Nginx Logs

Nginx logs provide valuable information for debugging and troubleshooting various issues, including the 502 Bad Gateway error. By analyzing the logs, you can gain insights into the underlying causes of the error and take appropriate actions to resolve it.

Example: Enabling Nginx Error Logging

To enable detailed error logging in Nginx, you can modify the Nginx configuration file:

http {
    # Enable error logging
    error_log /var/log/nginx/error.log;
    error_log /var/log/nginx/error.log notice;

    # Enable access logging
    access_log /var/log/nginx/access.log;
    access_log /var/log/nginx/access.log combined;

    # Additional log formats can be defined
    log_format mylog '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
    access_log /var/log/nginx/mylog.log mylog;
}

In this example, error_log is set to /var/log/nginx/error.log, which specifies the file where error logs will be written. The notice parameter indicates that only important events will be logged. Adjust the log level as needed for your debugging requirements.

The access_log directive specifies the file where access logs will be written. The combined parameter enables the logging of detailed information about each request, including the client IP, request time, response status, and more.

You can define custom log formats using the log_format directive. This allows you to specify the format of the log entries based on your specific needs.

By enabling and analyzing the Nginx error logs, you can gain valuable insights into the root causes of the 502 Bad Gateway error and take appropriate actions to resolve it.

Code Snippet Idea: Customizing Nginx Error Pages

Customizing Nginx error pages allows you to provide a more user-friendly and branded experience to your website visitors when they encounter errors, including the 502 Bad Gateway error. Instead of displaying the default error page, you can create custom error pages that match the look and feel of your website.

To customize Nginx error pages, you can modify the Nginx configuration file:

http {
    # Define the error pages
    error_page 502 /custom-error-pages/502.html;

    # Configure the location for serving the error pages
    location /custom-error-pages/ {
        root /path/to/error-pages;
        internal;
    }
}

In this example, the error_page directive specifies the URL and path to the custom error page for the 502 error. The path is relative to the document root specified in the Nginx configuration.

The location directive is used to configure the location for serving the error pages. The root directive specifies the directory where the error pages are located. The internal parameter ensures that the error pages are only accessible internally and not directly by clients.

By customizing the Nginx error pages, you can provide a more personalized and informative experience to your users, helping them understand the nature of the error and guiding them towards a possible solution.

Related Article: Tutorial: Working with Stacks in C

Code Snippet Idea: Configuring Nginx Reverse Proxy

Nginx can be used as a reverse proxy to distribute incoming requests to multiple backend servers. This allows you to scale your application horizontally and improve its performance and reliability. Configuring Nginx as a reverse proxy is straightforward and can be done by modifying the Nginx configuration file.

Here is an example configuration for setting up Nginx as a reverse proxy:

http {
    upstream backend_servers {
        server backend1.example.com;
        server backend2.example.com;
        server backend3.example.com;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this example, the upstream directive defines a group of backend servers that Nginx will proxy requests to. The server directives within the upstream block specify the addresses of the backend servers.

The server block within the http block defines the Nginx server configuration. The listen directive specifies the port on which Nginx listens for incoming requests. The server_name directive sets the domain name for the server.

The location block handles the requests for the specified location. The proxy_pass directive forwards the requests to the backend servers defined in the upstream block. The proxy_set_header directives are used to set the appropriate headers for the proxy request.

By configuring Nginx as a reverse proxy, you can distribute the incoming requests across multiple backend servers, improving the scalability and performance of your application.

Code Snippet Idea: Increasing Buffer and Timeout Limits

In some cases, the 502 Bad Gateway error can occur due to large request or response sizes that exceed the default buffer and timeout limits of Nginx. To address this issue, you can increase the buffer and timeout limits in the Nginx configuration file.

Here is an example of how to increase buffer and timeout limits in Nginx:

http {
    # Increase the buffer size to handle larger requests
    client_header_buffer_size 1k;
    large_client_header_buffers 4 4k;

    # Increase the timeout values for handling requests and responses
    client_body_timeout 60s;
    client_header_timeout 60s;
    send_timeout 60s;
}

In this example, client_header_buffer_size sets the buffer size for the request headers. Increasing this value allows Nginx to handle larger header sizes.

The large_client_header_buffers directive sets the number and size of buffers used for large request headers. This ensures that Nginx can handle larger requests without encountering buffer overflow errors.

The client_body_timeout directive specifies the maximum time Nginx waits for the entire request body to be received. The client_header_timeout directive sets the maximum time for receiving the request headers. The send_timeout directive sets the maximum time for sending the response to the client.

By increasing the buffer and timeout limits, you can handle larger requests and responses, reducing the occurrence of the 502 Bad Gateway error.

Code Snippet Idea: Implementing Health Checks

Implementing health checks for your backend servers can help identify and remove unhealthy servers from the load balancing pool, preventing the occurrence of the 502 Bad Gateway error. Nginx provides various mechanisms to perform health checks and dynamically adjust the upstream server configuration.

Here is an example of how to implement health checks in Nginx:

http {
    upstream backend_servers {
        server backend1.example.com;
        server backend2.example.com;

        # Enable health checks for backend1.example.com
        server backend1.example.com max_fails=3 fail_timeout=30s;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this example, the upstream directive defines a group of backend servers. The server directives within the upstream block specify the addresses of the backend servers.

The max_fails parameter specifies the maximum number of failed health checks before considering a server as unhealthy. The fail_timeout parameter sets the time after which a server is considered healthy again after a failure.

By enabling health checks, Nginx periodically checks the availability and responsiveness of the backend servers. If a server fails the health check, Nginx stops forwarding requests to that server until it becomes healthy again.

Implementing health checks ensures that only healthy servers receive incoming requests, reducing the occurrence of the 502 Bad Gateway error and improving the overall reliability of your application.

Related Article: How to Reverse a Linked List in Python, C and Java

Code Snippet Idea: Configuring Load Balancing

Load balancing is a technique used to distribute incoming network traffic across multiple servers to improve performance, scalability, and reliability. Nginx provides built-in load balancing capabilities, allowing you to efficiently distribute the workload across multiple backend servers.

Here is an example of how to configure load balancing in Nginx:

http {
    upstream backend_servers {
        server backend1.example.com;
        server backend2.example.com;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this example, the upstream directive defines a group of backend servers. The server directives within the upstream block specify the addresses of the backend servers.

The server block within the http block defines the Nginx server configuration. The listen directive specifies the port on which Nginx listens for incoming requests. The server_name directive sets the domain name for the server.

The location block handles the requests for the specified location. The proxy_pass directive forwards the requests to the backend servers defined in the upstream block. The proxy_set_header directives are used to set the appropriate headers for the proxy request.

By configuring load balancing in Nginx, you can distribute the incoming requests across multiple backend servers, improving the performance, scalability, and reliability of your application.

Error Handling: Interpreting Nginx Error Logs

Interpreting Nginx error logs is crucial for understanding the cause of the 502 Bad Gateway error and resolving it effectively. Nginx error logs provide detailed information about the errors encountered during request handling, allowing you to diagnose and troubleshoot the underlying issues.

To interpret Nginx error logs, you can access the error log file specified in the Nginx configuration. The default location for the error log file is typically /var/log/nginx/error.log.

By analyzing the error log file, you can look for specific error codes, timestamps, and other relevant information to identify the root cause of the 502 error. Common error codes associated with the 502 error include 502, 503, and 504.

Additionally, Nginx error logs may contain valuable information about upstream servers, timeouts, connectivity issues, and other related errors that can help pinpoint the source of the problem.

By understanding and interpreting the Nginx error logs, you can effectively troubleshoot and resolve the 502 Bad Gateway error, ensuring the smooth operation of your web application.

Use Case: Secure Application

Ensuring the security of your application is of utmost importance. Nginx provides various features and best practices that can help secure your application and protect it from potential attacks and vulnerabilities.

Related Article: How to Ignore Case Sensitivity with Regex (Case Insensitive)

Example: Enabling SSL/TLS

Enabling SSL/TLS encryption for your application is essential to protect sensitive user data and ensure secure communication between clients and the server. Nginx supports SSL/TLS out of the box and provides simple configuration options to enable it.

To enable SSL/TLS in Nginx, you need an SSL/TLS certificate issued by a trusted certificate authority. Once you have obtained the certificate, you can configure Nginx to use it:

http {
    server {
        listen 443 ssl;
        server_name example.com;

        ssl_certificate /path/to/certificate.crt;
        ssl_certificate_key /path/to/private.key;

        location / {
            # Your application configuration
        }
    }
}

In this example, the listen directive specifies the SSL/TLS-enabled port (443) and enables SSL/TLS for the server block. The server_name directive sets the domain name for the server.

The ssl_certificate and ssl_certificate_key directives specify the paths to the SSL/TLS certificate and private key files, respectively. Replace /path/to/certificate.crt and /path/to/private.key with the actual file paths on your server.

By enabling SSL/TLS encryption, you can secure the communication between your application and its users, protecting sensitive data from unauthorized access.

Best Practice: Regularly Updating Nginx

Regularly updating Nginx to the latest version is a recommended best practice to ensure the security, stability, and performance of your web server. Nginx releases updates periodically, addressing security vulnerabilities, introducing new features, and improving overall performance.

To update Nginx, follow the official documentation specific to your operating system and package manager. Generally, the update process involves running a system update command, such as apt update or yum update, to fetch the latest packages and then restarting the Nginx service.

It is also recommended to keep backups of your Nginx configuration files and relevant data before performing updates to mitigate any potential issues that may arise.

By regularly updating Nginx, you can benefit from the latest security patches, bug fixes, and performance improvements, ensuring a secure and reliable web server.

Real World Example: Resolving 502 Error on a Content Management System

In a real-world scenario, consider a content management system (CMS) that utilizes Nginx as a reverse proxy to serve dynamic web pages. Users of the CMS start experiencing intermittent 502 Bad Gateway errors, hampering their ability to manage content effectively.

To troubleshoot and resolve this issue, the following steps can be taken:

Related Article: How to Use the Regex Negation (Not) Operator

Step 1: Inspect Nginx Configuration

First, inspect the Nginx configuration files to ensure there are no misconfigurations or issues with proxying requests to the backend CMS application. Pay close attention to the proxy_pass directive and ensure it points to the correct backend server addresses.

Step 2: Check Backend Application Logs

Next, check the logs of the backend CMS application for any errors or issues. The backend application logs may provide insights into any misconfigurations, performance bottlenecks, or errors that could cause the 502 errors.

Step 3: Monitor Server Resources

Monitor the server resources, including CPU, memory, and disk usage, to identify any performance bottlenecks or resource limitations. High resource utilization can lead to slow response times or failures, resulting in the 502 error. Consider upgrading server hardware or optimizing the application code if necessary.

Related Article: How to Implement HTML Select Multiple As a Dropdown

Step 4: Optimize CMS Performance

Investigate potential optimizations for the CMS application itself. This may include optimizing database queries, caching frequently accessed data, or implementing performance improvements suggested by the CMS vendor.

Step 5: Implement Load Balancing and Caching

Consider implementing load balancing and caching techniques to distribute the workload across multiple backend servers and reduce the load on individual servers. Load balancing helps improve the scalability and availability of the CMS, while caching can significantly reduce the response time for frequently accessed content.

Step 6: Monitor and Fine-Tune Nginx Configuration

Continuously monitor the Nginx error logs, access logs, and performance metrics to identify any issues or bottlenecks. Fine-tune the Nginx configuration settings, such as worker processes, worker connections, and timeout values, based on the observed behavior and requirements of the CMS.

Related Article: How to Restrict HTML File Input to Only PDF and XLS

Performance Consideration: Load Balancing and Server Health Checks

Load balancing and server health checks are crucial for ensuring high availability and optimal performance in a distributed system. Nginx provides built-in load balancing capabilities and health check mechanisms that can be leveraged to distribute traffic efficiently and detect and remove unhealthy servers from the load balancing pool.

Load balancing involves distributing incoming requests across multiple backend servers to evenly distribute the workload and prevent any single server from becoming a bottleneck.

Server health checks periodically verify the availability and responsiveness of backend servers. If a server fails a health check, Nginx removes it from the pool, ensuring that only healthy servers receive incoming requests.

By combining load balancing with server health checks, you can ensure that traffic is distributed evenly across healthy servers, improving performance and preventing the occurrence of the 502 Bad Gateway error.

Advanced Technique: Using Nginx Debugging Mode

Nginx provides a debugging mode that can be enabled to obtain detailed information about the internal workings of the server. Debugging mode helps in diagnosing complex issues and identifying the root cause of errors, such as the 502 Bad Gateway error.

To enable debugging mode in Nginx, the server must be compiled with the --with-debug configuration option. This option adds additional debug information to the binary.

To start Nginx in debugging mode, use the following command:

nginx -g 'daemon off; master_process on; debug_points abort;'

This command starts Nginx without forking into the background and enables debugging output. The debug_points abort; directive instructs Nginx to abort execution at the first error encountered, providing detailed debug information.

By running Nginx in debugging mode, you can obtain valuable insights into the internal state of the server, helping in the diagnosis and resolution of complex issues like the 502 error.

Error Handling: Properly Restarting Nginx

Restarting Nginx properly is essential to ensure a smooth transition without interrupting the serving of requests. Improper restarts can lead to temporary failures and potentially cause the 502 Bad Gateway error.

To restart Nginx properly, follow these steps:

1. Check the Nginx configuration for any syntax errors using the following command:

nginx -t

Fix any reported errors before proceeding.

2. Gracefully stop the running Nginx process using the following command:

nginx -s quit

This command sends a signal to the Nginx process, allowing it to finish processing current requests and shutdown gracefully.

3. Start Nginx using the following command:

nginx

This will start a fresh instance of Nginx with the updated configuration.

You May Also Like

What is Test-Driven Development? (And How To Get It Right)

Test-Driven Development, or TDD, is a software development approach that focuses on writing tests before writing the actual code. By following a set of steps, developers... read more

16 Amazing Python Libraries You Can Use Now

In this article, we will introduce you to 16 amazing Python libraries that are widely used by top software teams. These libraries are powerful tools that can enhance... read more

Agile Shortfalls and What They Mean for Developers

What is the best software development methodology to use? This question is the topic of hot debate during the project implementation stage. However, what you choose... read more

24 influential books programmers should read

The fast-paced world of programming demands that people remain up-to-date. In fact, getting ahead of the curve makes a programmer stand out in his professional field.... read more

The issue with Monorepos

A monorepo is an arrangement where a single version control system (VCS) repository is used for all the code and projects in an organization. In this article, we will... read more

The most common wastes of software development (and how to reduce them)

Software development is a complex endeavor that requires much time to be spent by a highly-skilled, knowledgeable, and educated team of people. Often, there are time... read more