Question

Which one to use for my App back-end: Nginx or Apache?

I have this app/social network i’m about to launch. The back-end uses PHP+ MySQL to serve the Mobile app (iOS and Android) I read a lot of things but they are very confused. They are not CLEAR if an application using APACHE (get data from database receiving in json, load images, load and send messages, post text, etc) will really be faster just because it’s a dynamic content WHEN we’re scaling (like many people using at the same time). Some say it’s the same, some say apache is faster, some test i saw showed nginx faster than apache even for dynamic content when there’s more than 10 requests at the same time. Anyone would tell me if an API (php+mysql) for a mobile app would be faster on APACHE or NGINX? (DEFAULT installation, im not talking about ninja tricks) ??

Subscribe
Share

@MrCruz

Leaving this one as a comment rather than an answer since it’s just a link, but here’s a rather good comparison between the two posted by one of DigitalOcean’s own.

https://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations


Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Accepted Answer

@MrCruz Apache with mod_php is a bit faster than Nginx with php-fpm. I love the simplicity of Nginx and would always go with that. And I find it much easier setting up multiple Nginx in load balancing, which is great for scaling.

But talking about speed and serving dynamic content, then it really hasn’t much to do with Apache or Nginx. Since you need to make sure your application will respond as fast as possible, so it doesn’t hold up one of the connections in Apache/Nginx. So this leads us to PHP and MySQL.

You’ll get much more difference in what version of PHP you’re running. Nothing below version 7.0 is worth looking at, since it’s almost twice as fast as earlier versions.

You might want to switch from MySQL to MariaDB, since it has some extra features. And remember to create correct indexes in your database, since that can easily make 10x the speed difference. Actually you should be using PostgreSQL with it’s JSON storage, but that would be a big change, so let’s skip that.

Make sure everything is cut to the bone and optimized. Optimization/tweaking/tuning actually makes a huge difference. If you’re not interested in that, then just spend more on CPU/RAM and that’ll “fix” it.

I would do a Nginx, php-fpm, MariaDB, and cache with memcached or Redis. All of these can be setup on the same server or each on their own server and multiplied for scale.

Dang, just reloaded and saw the typical great answer from @jtittle :-)

@MrCruz

LTS = Long-Term Support Release. This means that Ubuntu 16.04 will continue to receive updates for a period of 5 years from the date of release. A non-LTS release, such as 16.10, will not.

As far as Ubuntu 16.04 goes, the commands to add the MariaDB repository would be:

sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu xenial main'
sudo apt-get update
sudo apt-get -y install mariadb-server

@MrCruz

Personally, I’d recommend NGINX over Apache. I find that configuring + optimizing NGINX is far less a chore than it is with Apache, it works out of the box with fastcgi using PHP-FPM (without having to use a module), and it’s also very simple to configure as a web server, reverse proxy, or even a load balancer.

That being said, while the default configuration may work short-term, at some point, to achieve a level of performance needed for your application to scale, you will have to modify configuration and begin tweaking configuration files. There’s really no way around that. The default configuration with NGINX and Apache is meant to get you started, but it’s not really intended for full-on production usage.

The same can be said of PHP/PHP-FPM, MySQL/MariaDB/Percona, etc. Base or stock installations are just a means to get you started. At some point, you’ll have to dive in or hire a sysadmin to do the work for you if you plan on scaling as there’s only so many cases where you can throw hardware at an issue before it no longer works. In doing so, you’ll also end up spending more trying to cope with load than you would hiring a sysadmin to manage it for you (if you’re not comfortable or capable of working from the CLI on your own).

This comment has been deleted

@MrCruz

Yeah, it’s only on 10.2.x right now, which is an RC (Release Candidate) – thus it may not be as stable.

You can remove the existing repository by removing the entry from either:

/etc/apt/sources.list

or by removing the file from:

/etc/apt/sources.list.d/

and then add the 10.2.x repository using:

sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.2/ubuntu xenial main'
sudo apt-get update
service mysql stop
sudo apt-get -y upgrade

Which should upgrade the release for you.

@MrCruz

On MyISAM and Aria tables, as well as on InnoDB tables from MariaDB 10.2.2, MariaDB can create spatial indexes (an R-tree index) using syntax similar to that for creating regular indexes, but extended with the SPATIAL keyword. Currently, columns in spatial indexes must be declared NOT NULL.

https://mariadb.com/kb/en/mariadb/spatial-index/

@jtittle @hansen Do you guys know if it’s true that ONLY MySQL (after 5.7.5) can have InnoDB with spatial indexes and MariaDB and Percona can’t? If they can’t i will switch to MySQL… localized index is a huge point for my design.I can’t ignore it

@MrCruz @hansen

Quick note about G Suite and using SMTP Relay – via https://support.google.com/a/answer/2956491#sendinglimitsforrelay

A registered G Suite user can’t relay more than 10,000 messages in a 24-hour period, and can’t relay messages to more than 10,000 unique recipients per 24-hour period. Users exceeding either of these limits see the error 550 5.4.5 Daily SMTP relay limit exceeded for user.

If you’re using PHP’s mail() function alone, that’s going to be your issue. Your best option would be to use something like SwiftMail or PHPMailer, which will allow you to connect over SMTP with ease.

Why? PHP’s mail function can be setup to use defined configuration in your php.ini file, though it’s a hassle and what you set there applies globally. If you need to change, you have to modify that file to instead of simply defining in-app. There’s really no reason to use php.ini as it’s counterproductive (in this specific case).

Unless you have a valid, working local mail server setup with at least SPF + DKIM (confirmed valid), the majority of mail sent will land in SPAM/Junk, if it’s not rejected altogether.

The reason for the above is pretty simple; it’s super-easy to abuse PHP’s mail() function and it takes very little code to do it. A simple foreach() or while() loop with a timer could send tens of thousands of e-mails in no time.

For example, let’s look at something very basic. This won’t actually work as there’s no data – even with data, it’s still relying on PHP’s mail() function, so it’ll all go to SPAM/Junk, but it serves a purpose for this example.

Note: This is a quick 5 minute script, it’s not meant to be clean, pretty, etc. It’s just an example :-).

<?php
/**
 * Returns a random key from the provided array.
 */
function pickRand( array $from )
{
    return array_rand( $from );
}

/**
 * Sends way too many e-mails. If this actually caused mail to
 * land in a users inbox, it'd be relatively easy to flood an
 * inbox in seconds or minutes.
 */
function mailBomb( array $to, array $subjects, array $messages, $delay = 5 )
{    
    foreach ( $to as $recipient )
    {
        $subjectKey = pickRand( $subjects );
        $message    = ( array_key_exists( $randomSubjectKey, $messages ) )
                    ? $messages[ $randomSubjectKey ]
                    : $messages[ pickRand( $messages ) ];

        foreach ( $to as $recipient )
        {
            mail(
                $recipient,
                $subjects[ $subjectKey ],
                $message,
                'From: well.known@company.com' . "\r\n" .
                'Reply-To: fake.email@spammer.com'
            );

            sleep( $delay );
        }
    }
}

/**
 * Fictional array containing 10,000+ e-mail addresses.
 * i.e. user.name@domain.ext ...
 */
$to         =   [];

/**
 * Fictional array containing 10,000+ e-mail subjects.
 * i.e. You've Won XYZ from PBC....
 */
$subjects   =   [];

/**
 * Fictional array containing 10,000+ e-mail messages.
 * For the purpose of this example, the key would match
 * a key in our $subject array.
 */
$messages   =   [];

/**
 * Run mailBomb Function
 */
mailBomb( $to, $subjects, $messages );

Now, the above would easily send any number of e-mails with a randomly selected subject and message using a fake e-mail as the sender (which may appear as if it’s coming from a reputable company) and a reply-to set as the spammers e-mail. If you didn’t look at the headers (and most people don’t), you might just reply.

Now you might say well when they reply back, they’ll reveal their real e-mail; not so. They could be filtering e-mail through a PHP script and then sending mail back out through another designed to keep the forged e-mail in-tact.

That’s why you don’t use mail() alone and why you either:

1). Setup a real mail server (on a separate server) and make sure it’s in working order, or;

2). Use MailGun, SendGrid, Amazon, etc.

When combined with the mail libraries I noted above, those in #2 will help you to land your e-mail where it belongs instead of troubleshooting #1.

@MrCruz Hmmm… If you’ve installed Postfix, then Sendmail isn’t used any longer. But I have no idea if you’ve messed around in some of the general files used by both - like /etc/mailhost and more.

If you only have access to a regular Gmail account (gmail.com), then that is not going to suffice and will also look unprofessional. And I don’t remember the limit on Gmail, but I think it’s 500 mails per day. When I said Google Apps (aka G Suite, stupid name), it has a much higher limit and will send as yourdomain.tld I agree with @jtittle that using an API to send mail will give you more control, but I usually recommend SMTP-relays, since it allows you to connect to almost every application. You need something that will allow you to send 40k emails weekly at minimum, since that’s the number of new users you expect - and you want to send from welcome@yourdomain.tld - so Gmail is not an option at all. Mailgun, SendGrid, Amazon SES will allow that, and I’m actually unsure if Google Apps will allow that limit.

And you need to show the failure of your PHP mailing script - add debug level. If PHP doesn’t fail (makes a script failure), then we need to see /var/log/mail.log and /var/log/mail.err

@hansen @jtittle Boy i feel dumb. EVERYTHING works fine but the damn PHP mailing (using smtp trying to login to google account - G Suite) I tried Postfix and Sendmail many times, installing and re-installing, one or the other or both. None get my PHP code to work. With sendmail using terminal it says it works (it shows sent mails) but it doesn’t send emails to anybody. And i need it to be done through PHP code. But using gmail.com the account i created using my domain, it works just fine. It receives emails and it sends emails. But can’t even use any Mail.php or anything similar to connect to via smtp using PHP. I feel like it’s something very small and stupid that i missed.

@hansen @jtittle Guys, THANK YOU VERY VERY MUCH… IT IS WORKING LIKE A CHARM… Everything MariaDB, PHP, Nginx, HTTPS … my app connected using secure connection… pretty cool… Now, there’s only one thing bothering me… the Mailing from PHP… idk if i installed the sendmail wrong… idk… but it isn’t working as it does at my old server. My PHP signup script has to send an email to the user… The MX records are already set and working with gmail account. But currently the PHP mailing isn’t working Do you guys have anything for me to allow my PHP script to send emails?